Commit c69e8d9c authored by David Howells's avatar David Howells Committed by James Morris

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: default avatarDavid Howells <dhowells@redhat.com>
Acked-by: default avatarJames Morris <jmorris@namei.org>
Acked-by: default avatarSerge Hallyn <serue@us.ibm.com>
Signed-off-by: default avatarJames Morris <jmorris@namei.org>
parent 86a264ab
...@@ -2399,25 +2399,33 @@ pfm_smpl_buffer_alloc(struct task_struct *task, struct file *filp, pfm_context_t ...@@ -2399,25 +2399,33 @@ pfm_smpl_buffer_alloc(struct task_struct *task, struct file *filp, pfm_context_t
static int static int
pfm_bad_permissions(struct task_struct *task) pfm_bad_permissions(struct task_struct *task)
{ {
const struct cred *tcred;
uid_t uid = current_uid(); uid_t uid = current_uid();
gid_t gid = current_gid(); gid_t gid = current_gid();
int ret;
rcu_read_lock();
tcred = __task_cred(task);
/* inspired by ptrace_attach() */ /* inspired by ptrace_attach() */
DPRINT(("cur: uid=%d gid=%d task: euid=%d suid=%d uid=%d egid=%d sgid=%d\n", DPRINT(("cur: uid=%d gid=%d task: euid=%d suid=%d uid=%d egid=%d sgid=%d\n",
uid, uid,
gid, gid,
task->euid, tcred->euid,
task->suid, tcred->suid,
task->uid, tcred->uid,
task->egid, tcred->egid,
task->sgid)); tcred->sgid));
return (uid != task->euid) ret = ((uid != tcred->euid)
|| (uid != task->suid) || (uid != tcred->suid)
|| (uid != task->uid) || (uid != tcred->uid)
|| (gid != task->egid) || (gid != tcred->egid)
|| (gid != task->sgid) || (gid != tcred->sgid)
|| (gid != task->gid)) && !capable(CAP_SYS_PTRACE); || (gid != tcred->gid)) && !capable(CAP_SYS_PTRACE);
rcu_read_unlock();
return ret;
} }
static int static int
......
...@@ -106,6 +106,7 @@ void proc_id_connector(struct task_struct *task, int which_id) ...@@ -106,6 +106,7 @@ void proc_id_connector(struct task_struct *task, int which_id)
struct proc_event *ev; struct proc_event *ev;
__u8 buffer[CN_PROC_MSG_SIZE]; __u8 buffer[CN_PROC_MSG_SIZE];
struct timespec ts; struct timespec ts;
const struct cred *cred;
if (atomic_read(&proc_event_num_listeners) < 1) if (atomic_read(&proc_event_num_listeners) < 1)
return; return;
...@@ -115,14 +116,19 @@ void proc_id_connector(struct task_struct *task, int which_id) ...@@ -115,14 +116,19 @@ void proc_id_connector(struct task_struct *task, int which_id)
ev->what = which_id; ev->what = which_id;
ev->event_data.id.process_pid = task->pid; ev->event_data.id.process_pid = task->pid;
ev->event_data.id.process_tgid = task->tgid; ev->event_data.id.process_tgid = task->tgid;
rcu_read_lock();
cred = __task_cred(task);
if (which_id == PROC_EVENT_UID) { if (which_id == PROC_EVENT_UID) {
ev->event_data.id.r.ruid = task->cred->uid; ev->event_data.id.r.ruid = cred->uid;
ev->event_data.id.e.euid = task->cred->euid; ev->event_data.id.e.euid = cred->euid;
} else if (which_id == PROC_EVENT_GID) { } else if (which_id == PROC_EVENT_GID) {
ev->event_data.id.r.rgid = task->cred->gid; ev->event_data.id.r.rgid = cred->gid;
ev->event_data.id.e.egid = task->cred->egid; ev->event_data.id.e.egid = cred->egid;
} else } else {
rcu_read_unlock();
return; return;
}
rcu_read_unlock();
get_seq(&msg->seq, &ev->cpu); get_seq(&msg->seq, &ev->cpu);
ktime_get_ts(&ts); /* get high res monotonic timestamp */ ktime_get_ts(&ts); /* get high res monotonic timestamp */
put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
......
...@@ -1361,6 +1361,7 @@ static void fill_prstatus(struct elf_prstatus *prstatus, ...@@ -1361,6 +1361,7 @@ static void fill_prstatus(struct elf_prstatus *prstatus,
static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p, static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
struct mm_struct *mm) struct mm_struct *mm)
{ {
const struct cred *cred;
unsigned int i, len; unsigned int i, len;
/* first copy the parameters from user space */ /* first copy the parameters from user space */
...@@ -1388,8 +1389,11 @@ static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p, ...@@ -1388,8 +1389,11 @@ static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
psinfo->pr_zomb = psinfo->pr_sname == 'Z'; psinfo->pr_zomb = psinfo->pr_sname == 'Z';
psinfo->pr_nice = task_nice(p); psinfo->pr_nice = task_nice(p);
psinfo->pr_flag = p->flags; psinfo->pr_flag = p->flags;
SET_UID(psinfo->pr_uid, p->cred->uid); rcu_read_lock();
SET_GID(psinfo->pr_gid, p->cred->gid); cred = __task_cred(p);
SET_UID(psinfo->pr_uid, cred->uid);
SET_GID(psinfo->pr_gid, cred->gid);
rcu_read_unlock();
strncpy(psinfo->pr_fname, p->comm, sizeof(psinfo->pr_fname)); strncpy(psinfo->pr_fname, p->comm, sizeof(psinfo->pr_fname));
return 0; return 0;
......
...@@ -1414,6 +1414,7 @@ static void fill_prstatus(struct elf_prstatus *prstatus, ...@@ -1414,6 +1414,7 @@ static void fill_prstatus(struct elf_prstatus *prstatus,
static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p, static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
struct mm_struct *mm) struct mm_struct *mm)
{ {
const struct cred *cred;
unsigned int i, len; unsigned int i, len;
/* first copy the parameters from user space */ /* first copy the parameters from user space */
...@@ -1441,8 +1442,11 @@ static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p, ...@@ -1441,8 +1442,11 @@ static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
psinfo->pr_zomb = psinfo->pr_sname == 'Z'; psinfo->pr_zomb = psinfo->pr_sname == 'Z';
psinfo->pr_nice = task_nice(p); psinfo->pr_nice = task_nice(p);
psinfo->pr_flag = p->flags; psinfo->pr_flag = p->flags;
SET_UID(psinfo->pr_uid, p->cred->uid); rcu_read_lock();
SET_GID(psinfo->pr_gid, p->cred->gid); cred = __task_cred(p);
SET_UID(psinfo->pr_uid, cred->uid);
SET_GID(psinfo->pr_gid, cred->gid);
rcu_read_unlock();
strncpy(psinfo->pr_fname, p->comm, sizeof(psinfo->pr_fname)); strncpy(psinfo->pr_fname, p->comm, sizeof(psinfo->pr_fname));
return 0; return 0;
......
...@@ -401,10 +401,17 @@ static const long band_table[NSIGPOLL] = { ...@@ -401,10 +401,17 @@ static const long band_table[NSIGPOLL] = {
static inline int sigio_perm(struct task_struct *p, static inline int sigio_perm(struct task_struct *p,
struct fown_struct *fown, int sig) struct fown_struct *fown, int sig)
{ {
return (((fown->euid == 0) || const struct cred *cred;
(fown->euid == p->cred->suid) || (fown->euid == p->cred->uid) || int ret;
(fown->uid == p->cred->suid) || (fown->uid == p->cred->uid)) &&
!security_file_send_sigiotask(p, fown, sig)); rcu_read_lock();
cred = __task_cred(p);
ret = ((fown->euid == 0 ||
fown->euid == cred->suid || fown->euid == cred->uid ||
fown->uid == cred->suid || fown->uid == cred->uid) &&
!security_file_send_sigiotask(p, fown, sig));
rcu_read_unlock();
return ret;
} }
static void send_sigio_to_task(struct task_struct *p, static void send_sigio_to_task(struct task_struct *p,
......
...@@ -869,18 +869,25 @@ int fuse_update_attributes(struct inode *inode, struct kstat *stat, ...@@ -869,18 +869,25 @@ int fuse_update_attributes(struct inode *inode, struct kstat *stat,
*/ */
int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task) int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task)
{ {
const struct cred *cred;
int ret;
if (fc->flags & FUSE_ALLOW_OTHER) if (fc->flags & FUSE_ALLOW_OTHER)
return 1; return 1;
if (task->cred->euid == fc->user_id && rcu_read_lock();
task->cred->suid == fc->user_id && ret = 0;
task->cred->uid == fc->user_id && cred = __task_cred(task);
task->cred->egid == fc->group_id && if (cred->euid == fc->user_id &&
task->cred->sgid == fc->group_id && cred->suid == fc->user_id &&
task->cred->gid == fc->group_id) cred->uid == fc->user_id &&
return 1; cred->egid == fc->group_id &&
cred->sgid == fc->group_id &&
cred->gid == fc->group_id)
ret = 1;
rcu_read_unlock();
return 0; return ret;
} }
static int fuse_access(struct inode *inode, int mask) static int fuse_access(struct inode *inode, int mask)
......
...@@ -31,10 +31,16 @@ static int set_task_ioprio(struct task_struct *task, int ioprio) ...@@ -31,10 +31,16 @@ static int set_task_ioprio(struct task_struct *task, int ioprio)
{ {
int err; int err;
struct io_context *ioc; struct io_context *ioc;
const struct cred *cred = current_cred(), *tcred;
if (task->cred->uid != current_euid() && rcu_read_lock();
task->cred->uid != current_uid() && !capable(CAP_SYS_NICE)) tcred = __task_cred(task);
if (tcred->uid != cred->euid &&
tcred->uid != cred->uid && !capable(CAP_SYS_NICE)) {
rcu_read_unlock();
return -EPERM; return -EPERM;
}
rcu_read_unlock();
err = security_task_setioprio(task, ioprio); err = security_task_setioprio(task, ioprio);
if (err) if (err)
...@@ -131,7 +137,7 @@ asmlinkage long sys_ioprio_set(int which, int who, int ioprio) ...@@ -131,7 +137,7 @@ asmlinkage long sys_ioprio_set(int which, int who, int ioprio)
break; break;
do_each_thread(g, p) { do_each_thread(g, p) {
if (p->cred->uid != who) if (__task_cred(p)->uid != who)
continue; continue;
ret = set_task_ioprio(p, ioprio); ret = set_task_ioprio(p, ioprio);
if (ret) if (ret)
...@@ -224,7 +230,7 @@ asmlinkage long sys_ioprio_get(int which, int who) ...@@ -224,7 +230,7 @@ asmlinkage long sys_ioprio_get(int which, int who)
break; break;
do_each_thread(g, p) { do_each_thread(g, p) {
if (p->cred->uid != user->uid) if (__task_cred(p)->uid != user->uid)
continue; continue;
tmpio = get_task_ioprio(p); tmpio = get_task_ioprio(p);
if (tmpio < 0) if (tmpio < 0)
......
...@@ -159,6 +159,7 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns, ...@@ -159,6 +159,7 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
struct group_info *group_info; struct group_info *group_info;
int g; int g;
struct fdtable *fdt = NULL; struct fdtable *fdt = NULL;
const struct cred *cred;
pid_t ppid, tpid; pid_t ppid, tpid;
rcu_read_lock(); rcu_read_lock();
...@@ -170,6 +171,7 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns, ...@@ -170,6 +171,7 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
if (tracer) if (tracer)
tpid = task_pid_nr_ns(tracer, ns); tpid = task_pid_nr_ns(tracer, ns);
} }
cred = get_cred((struct cred *) __task_cred(p));
seq_printf(m, seq_printf(m,
"State:\t%s\n" "State:\t%s\n"
"Tgid:\t%d\n" "Tgid:\t%d\n"
...@@ -182,8 +184,8 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns, ...@@ -182,8 +184,8 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
task_tgid_nr_ns(p, ns), task_tgid_nr_ns(p, ns),
pid_nr_ns(pid, ns), pid_nr_ns(pid, ns),
ppid, tpid, ppid, tpid,
p->cred->uid, p->cred->euid, p->cred->suid, p->cred->fsuid, cred->uid, cred->euid, cred->suid, cred->fsuid,
p->cred->gid, p->cred->egid, p->cred->sgid, p->cred->fsgid); cred->gid, cred->egid, cred->sgid, cred->fsgid);
task_lock(p); task_lock(p);
if (p->files) if (p->files)
...@@ -194,13 +196,12 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns, ...@@ -194,13 +196,12 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
fdt ? fdt->max_fds : 0); fdt ? fdt->max_fds : 0);
rcu_read_unlock(); rcu_read_unlock();
group_info = p->cred->group_info; group_info = cred->group_info;
get_group_info(group_info);
task_unlock(p); task_unlock(p);
for (g = 0; g < min(group_info->ngroups, NGROUPS_SMALL); g++) for (g = 0; g < min(group_info->ngroups, NGROUPS_SMALL); g++)
seq_printf(m, "%d ", GROUP_AT(group_info, g)); seq_printf(m, "%d ", GROUP_AT(group_info, g));
put_group_info(group_info); put_cred(cred);
seq_printf(m, "\n"); seq_printf(m, "\n");
} }
...@@ -262,7 +263,7 @@ static inline void task_sig(struct seq_file *m, struct task_struct *p) ...@@ -262,7 +263,7 @@ static inline void task_sig(struct seq_file *m, struct task_struct *p)
blocked = p->blocked; blocked = p->blocked;
collect_sigign_sigcatch(p, &ignored, &caught); collect_sigign_sigcatch(p, &ignored, &caught);
num_threads = atomic_read(&p->signal->count); num_threads = atomic_read(&p->signal->count);
qsize = atomic_read(&p->cred->user->sigpending); qsize = atomic_read(&__task_cred(p)->user->sigpending);
qlim = p->signal->rlim[RLIMIT_SIGPENDING].rlim_cur; qlim = p->signal->rlim[RLIMIT_SIGPENDING].rlim_cur;
unlock_task_sighand(p, &flags); unlock_task_sighand(p, &flags);
} }
...@@ -293,12 +294,21 @@ static void render_cap_t(struct seq_file *m, const char *header, ...@@ -293,12 +294,21 @@ static void render_cap_t(struct seq_file *m, const char *header,
static inline void task_cap(struct seq_file *m, struct task_struct *p) static inline void task_cap(struct seq_file *m, struct task_struct *p)
{ {
struct cred *cred = p->cred; const struct cred *cred;
kernel_cap_t cap_inheritable, cap_permitted, cap_effective, cap_bset;
render_cap_t(m, "CapInh:\t", &cred->cap_inheritable); rcu_read_lock();
render_cap_t(m, "CapPrm:\t", &cred->cap_permitted); cred = __task_cred(p);
render_cap_t(m, "CapEff:\t", &cred->cap_effective); cap_inheritable = cred->cap_inheritable;
render_cap_t(m, "CapBnd:\t", &cred->cap_bset); cap_permitted = cred->cap_permitted;
cap_effective = cred->cap_effective;
cap_bset = cred->cap_bset;
rcu_read_unlock();
render_cap_t(m, "CapInh:\t", &cap_inheritable);
render_cap_t(m, "CapPrm:\t", &cap_permitted);
render_cap_t(m, "CapEff:\t", &cap_effective);
render_cap_t(m, "CapBnd:\t", &cap_bset);
} }
static inline void task_context_switch_counts(struct seq_file *m, static inline void task_context_switch_counts(struct seq_file *m,
......
...@@ -1406,6 +1406,7 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st ...@@ -1406,6 +1406,7 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st
{ {
struct inode * inode; struct inode * inode;
struct proc_inode *ei; struct proc_inode *ei;
const struct cred *cred;
/* We need a new inode */ /* We need a new inode */
...@@ -1428,8 +1429,11 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st ...@@ -1428,8 +1429,11 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st
inode->i_uid = 0; inode->i_uid = 0;
inode->i_gid = 0; inode->i_gid = 0;
if (task_dumpable(task)) { if (task_dumpable(task)) {
inode->i_uid = task->cred->euid; rcu_read_lock();
inode->i_gid = task->cred->egid; cred = __task_cred(task);
inode->i_uid = cred->euid;
inode->i_gid = cred->egid;
rcu_read_unlock();
} }
security_task_to_inode(task, inode); security_task_to_inode(task, inode);
...@@ -1445,6 +1449,8 @@ static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat ...@@ -1445,6 +1449,8 @@ static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat
{ {
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
struct task_struct *task; struct task_struct *task;
const struct cred *cred;
generic_fillattr(inode, stat); generic_fillattr(inode, stat);
rcu_read_lock(); rcu_read_lock();
...@@ -1454,8 +1460,9 @@ static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat ...@@ -1454,8 +1460,9 @@ static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat
if (task) { if (task) {
if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) || if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) ||
task_dumpable(task)) { task_dumpable(task)) {
stat->uid = task->cred->euid; cred = __task_cred(task);
stat->gid = task->cred->egid; stat->uid = cred->euid;
stat->gid = cred->egid;
} }
} }
rcu_read_unlock(); rcu_read_unlock();
...@@ -1483,11 +1490,16 @@ static int pid_revalidate(struct dentry *dentry, struct nameidata *nd) ...@@ -1483,11 +1490,16 @@ static int pid_revalidate(struct dentry *dentry, struct nameidata *nd)
{ {
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
struct task_struct *task = get_proc_task(inode); struct task_struct *task = get_proc_task(inode);
const struct cred *cred;
if (task) { if (task) {
if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) || if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) ||
task_dumpable(task)) { task_dumpable(task)) {
inode->i_uid = task->cred->euid; rcu_read_lock();
inode->i_gid = task->cred->egid; cred = __task_cred(task);
inode->i_uid = cred->euid;
inode->i_gid = cred->egid;
rcu_read_unlock();
} else { } else {
inode->i_uid = 0; inode->i_uid = 0;
inode->i_gid = 0; inode->i_gid = 0;
...@@ -1649,6 +1661,7 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd) ...@@ -1649,6 +1661,7 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
struct task_struct *task = get_proc_task(inode); struct task_struct *task = get_proc_task(inode);
int fd = proc_fd(inode); int fd = proc_fd(inode);
struct files_struct *files; struct files_struct *files;
const struct cred *cred;
if (task) { if (task) {
files = get_files_struct(task); files = get_files_struct(task);
...@@ -1658,8 +1671,11 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd) ...@@ -1658,8 +1671,11 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
rcu_read_unlock(); rcu_read_unlock();
put_files_struct(files); put_files_struct(files);
if (task_dumpable(task)) { if (task_dumpable(task)) {
inode->i_uid = task->cred->euid; rcu_read_lock();
inode->i_gid = task->cred->egid; cred = __task_cred(task);
inode->i_uid = cred->euid;
inode->i_gid = cred->egid;
rcu_read_unlock();
} else { } else {
inode->i_uid = 0; inode->i_uid = 0;
inode->i_gid = 0; inode->i_gid = 0;
......
...@@ -147,8 +147,9 @@ static inline struct cred *get_cred(struct cred *cred) ...@@ -147,8 +147,9 @@ static inline struct cred *get_cred(struct cred *cred)
* Release a reference to a set of credentials, deleting them when the last ref * Release a reference to a set of credentials, deleting them when the last ref
* is released. * is released.
*/ */
static inline void put_cred(struct cred *cred) static inline void put_cred(const struct cred *_cred)
{ {
struct cred *cred = (struct cred *) _cred;
if (atomic_dec_and_test(&(cred)->usage)) if (atomic_dec_and_test(&(cred)->usage))
__put_cred(cred); __put_cred(cred);
} }
......
...@@ -447,7 +447,7 @@ static int audit_filter_rules(struct task_struct *tsk, ...@@ -447,7 +447,7 @@ static int audit_filter_rules(struct task_struct *tsk,
struct audit_names *name, struct audit_names *name,
enum audit_state *state) enum audit_state *state)
{ {
struct cred *cred = tsk->cred; const struct cred *cred = get_task_cred(tsk);
int i, j, need_sid = 1; int i, j, need_sid = 1;
u32 sid; u32 sid;
...@@ -642,8 +642,10 @@ static int audit_filter_rules(struct task_struct *tsk, ...@@ -642,8 +642,10 @@ static int audit_filter_rules(struct task_struct *tsk,
break; break;
} }
if (!result) if (!result) {
put_cred(cred);
return 0; return 0;
}
} }
if (rule->filterkey && ctx) if (rule->filterkey && ctx)
ctx->filterkey = kstrdup(rule->filterkey, GFP_ATOMIC); ctx->filterkey = kstrdup(rule->filterkey, GFP_ATOMIC);
...@@ -651,6 +653,7 @@ static int audit_filter_rules(struct task_struct *tsk, ...@@ -651,6 +653,7 @@ static int audit_filter_rules(struct task_struct *tsk,
case AUDIT_NEVER: *state = AUDIT_DISABLED; break; case AUDIT_NEVER: *state = AUDIT_DISABLED; break;
case AUDIT_ALWAYS: *state = AUDIT_RECORD_CONTEXT; break; case AUDIT_ALWAYS: *state = AUDIT_RECORD_CONTEXT; break;
} }
put_cred(cred);
return 1; return 1;
} }
...@@ -1229,7 +1232,7 @@ static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name) ...@@ -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) 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; int i, call_panic = 0;
struct audit_buffer *ab; struct audit_buffer *ab;
struct audit_aux_data *aux; struct audit_aux_data *aux;
...@@ -1239,13 +1242,14 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts ...@@ -1239,13 +1242,14 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
context->pid = tsk->pid; context->pid = tsk->pid;
if (!context->ppid) if (!context->ppid)
context->ppid = sys_getppid(); context->ppid = sys_getppid();
context->uid = cred->uid; cred = current_cred();
context->gid = cred->gid; context->uid = cred->uid;
context->euid = cred->euid; context->gid = cred->gid;
context->suid = cred->suid; context->euid = cred->euid;
context->suid = cred->suid;
context->fsuid = cred->fsuid; context->fsuid = cred->fsuid;
context->egid = cred->egid; context->egid = cred->egid;
context->sgid = cred->sgid; context->sgid = cred->sgid;
context->fsgid = cred->fsgid; context->fsgid = cred->fsgid;
context->personality = tsk->personality; context->personality = tsk->personality;
...@@ -2088,7 +2092,7 @@ int audit_set_loginuid(struct task_struct *task, uid_t loginuid) ...@@ -2088,7 +2092,7 @@ int audit_set_loginuid(struct task_struct *task, uid_t loginuid)
audit_log_format(ab, "login pid=%d uid=%u " audit_log_format(ab, "login pid=%d uid=%u "
"old auid=%u new auid=%u" "old auid=%u new auid=%u"
" old ses=%u new ses=%u", " old ses=%u new ses=%u",
task->pid, task->cred->uid, task->pid, task_uid(task),
task->loginuid, loginuid, task->loginuid, loginuid,
task->sessionid, sessionid); task->sessionid, sessionid);
audit_log_end(ab); audit_log_end(ab);
...@@ -2471,7 +2475,7 @@ void __audit_ptrace(struct task_struct *t) ...@@ -2471,7 +2475,7 @@ void __audit_ptrace(struct task_struct *t)
context->target_pid = t->pid; context->target_pid = t->pid;
context->target_auid = audit_get_loginuid(t); 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); context->target_sessionid = audit_get_sessionid(t);
security_task_getsecid(t, &context->target_sid); security_task_getsecid(t, &context->target_sid);
memcpy(context->target_comm, t->comm, TASK_COMM_LEN); memcpy(context->target_comm, t->comm, TASK_COMM_LEN);
...@@ -2490,6 +2494,7 @@ int __audit_signal_info(int sig, struct task_struct *t) ...@@ -2490,6 +2494,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
struct audit_aux_data_pids *axp; struct audit_aux_data_pids *axp;
struct task_struct *tsk = current; struct task_struct *tsk = current;
struct audit_context *ctx = tsk->audit_context; 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 (audit_pid && t->tgid == audit_pid) {
if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1 || sig == SIGUSR2) { if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1 || sig == SIGUSR2) {
...@@ -2497,7 +2502,7 @@ int __audit_signal_info(int sig, struct task_struct *t) ...@@ -2497,7 +2502,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
if (tsk->loginuid != -1) if (tsk->loginuid != -1)
audit_sig_uid = tsk->loginuid; audit_sig_uid = tsk->loginuid;
else else
audit_sig_uid = tsk->cred->uid; audit_sig_uid = uid;
security_task_getsecid(tsk, &audit_sig_sid); security_task_getsecid(tsk, &audit_sig_sid);
} }
if (!audit_signals || audit_dummy_context()) if (!audit_signals || audit_dummy_context())
...@@ -2509,7 +2514,7 @@ int __audit_signal_info(int sig, struct task_struct *t) ...@@ -2509,7 +2514,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
if (!ctx->target_pid) { if (!ctx->target_pid) {
ctx->target_pid = t->tgid; ctx->target_pid = t->tgid;
ctx->target_auid = audit_get_loginuid(t); 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); ctx->target_sessionid = audit_get_sessionid(t);
security_task_getsecid(t, &ctx->target_sid); security_task_getsecid(t, &ctx->target_sid);
memcpy(ctx->target_comm, t->comm, TASK_COMM_LEN); memcpy(ctx->target_comm, t->comm, TASK_COMM_LEN);
...@@ -2530,7 +2535,7 @@ int __audit_signal_info(int sig, struct task_struct *t) ...@@ -2530,7 +2535,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
axp->target_pid[axp->pid_count] = t->tgid; axp->target_pid[axp->pid_count] = t->tgid;
axp->target_auid[axp->pid_count] = audit_get_loginuid(t); 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); axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t);
security_task_getsecid(t, &axp->target_sid[axp->pid_count]); security_task_getsecid(t, &axp->target_sid[axp->pid_count]);
memcpy(axp->target_comm[axp->pid_count], t->comm, TASK_COMM_LEN); 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) ...@@ -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) static int attach_task_by_pid(struct cgroup *cgrp, u64 pid)
{ {
struct task_struct *tsk; struct task_struct *tsk;
uid_t euid; const struct cred *cred = current_cred(), *tcred;
int ret; int ret;
if (pid) { if (pid) {
...@@ -1289,16 +1289,16 @@ static int attach_task_by_pid(struct cgroup *cgrp, u64 pid) ...@@ -1289,16 +1289,16 @@ static int attach_task_by_pid(struct cgroup *cgrp, u64 pid)
rcu_read_unlock(); rcu_read_unlock();
return -ESRCH; return -ESRCH;
} }
get_task_struct(tsk);
rcu_read_unlock();
euid = current_euid(); tcred = __task_cred(tsk);
if (euid && if (cred->euid &&
euid != tsk->cred->uid && cred->euid != tcred->uid &&
euid != tsk->cred->suid) { cred->euid != tcred->suid) {
put_task_struct(tsk); rcu_read_unlock();
return -EACCES; return -EACCES;
} }
get_task_struct(tsk);
rcu_read_unlock();
} else { } else {
tsk = current; tsk = current;
get_task_struct(tsk); get_task_struct(tsk);
......
...@@ -160,7 +160,10 @@ void release_task(struct task_struct * p) ...@@ -160,7 +160,10 @@ void release_task(struct task_struct * p)
int zap_leader; int zap_leader;
repeat: repeat:
tracehook_prepare_release_task(p); 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); proc_flush_task(p);
write_lock_irq(&tasklist_lock); write_lock_irq(&tasklist_lock);
tracehook_finish_release_task(p); tracehook_finish_release_task(p);
...@@ -1267,12 +1270,12 @@ static int wait_task_zombie(struct task_struct *p, int options, ...@@ -1267,12 +1270,12 @@ static int wait_task_zombie(struct task_struct *p, int options,
unsigned long state; unsigned long state;
int retval, status, traced; int retval, status, traced;
pid_t pid = task_pid_vnr(p); pid_t pid = task_pid_vnr(p);
uid_t uid = __task_cred(p)->uid;
if (!likely(options & WEXITED)) if (!likely(options & WEXITED))
return 0; return 0;
if (unlikely(options & WNOWAIT)) { if (unlikely(options & WNOWAIT)) {
uid_t uid = p->cred->uid;
int exit_code = p->exit_code; int exit_code = p->exit_code;
int why, status; int why, status;
...@@ -1393,7 +1396,7 @@ static int wait_task_zombie(struct task_struct *p, int options, ...@@ -1393,7 +1396,7 @@ static int wait_task_zombie(struct task_struct *p, int options,
if (!retval && infop) if (!retval && infop)
retval = put_user(pid, &infop->si_pid); retval = put_user(pid, &infop->si_pid);
if (!retval && infop) if (!retval && infop)
retval = put_user(p->cred->uid, &infop->si_uid); retval = put_user(uid, &infop->si_uid);
if (!retval) if (!retval)
retval = pid; retval = pid;
...@@ -1458,7 +1461,8 @@ static int wait_task_stopped(int ptrace, struct task_struct *p, ...@@ -1458,7 +1461,8 @@ static int wait_task_stopped(int ptrace, struct task_struct *p,
if (!unlikely(options & WNOWAIT)) if (!unlikely(options & WNOWAIT))
p->exit_code = 0; 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: unlock_sig:
spin_unlock_irq(&p->sighand->siglock); spin_unlock_irq(&p->sighand->siglock);
if (!exit_code) if (!exit_code)
...@@ -1532,10 +1536,10 @@ static int wait_task_continued(struct task_struct *p, int options, ...@@ -1532,10 +1536,10 @@ static int wait_task_continued(struct task_struct *p, int options,
} }
if (!unlikely(options & WNOWAIT)) if (!unlikely(options & WNOWAIT))
p->signal->flags &= ~SIGNAL_STOP_CONTINUED; p->signal->flags &= ~SIGNAL_STOP_CONTINUED;
uid = __task_cred(p)->uid;
spin_unlock_irq(&p->sighand->siglock); spin_unlock_irq(&p->sighand->siglock);
pid = task_pid_vnr(p); pid = task_pid_vnr(p);
uid = p->cred->uid;
get_task_struct(p); get_task_struct(p);
read_unlock(&tasklist_lock); read_unlock(&tasklist_lock);
......
...@@ -439,15 +439,20 @@ static void free_pi_state(struct futex_pi_state *pi_state) ...@@ -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) static struct task_struct * futex_find_get_task(pid_t pid)
{ {
struct task_struct *p; struct task_struct *p;
uid_t euid = current_euid(); const struct cred *cred = current_cred(), *pcred;
rcu_read_lock(); rcu_read_lock();
p = find_task_by_vpid(pid); p = find_task_by_vpid(pid);
if (!p || (euid != p->cred->euid && if (!p) {
euid != p->cred->uid))
p = ERR_PTR(-ESRCH); p = ERR_PTR(-ESRCH);
else } else {
get_task_struct(p); 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(); rcu_read_unlock();
...@@ -1831,7 +1836,7 @@ sys_get_robust_list(int pid, struct robust_list_head __user * __user *head_ptr, ...@@ -1831,7 +1836,7 @@ sys_get_robust_list(int pid, struct robust_list_head __user * __user *head_ptr,
{ {
struct robust_list_head __user *head; struct robust_list_head __user *head;
unsigned long ret; unsigned long ret;
uid_t euid = current_euid(); const struct cred *cred = current_cred(), *pcred;
if (!futex_cmpxchg_enabled) if (!futex_cmpxchg_enabled)
return -ENOSYS; return -ENOSYS;
...@@ -1847,8 +1852,9 @@ sys_get_robust_list(int pid, struct robust_list_head __user * __user *head_ptr, ...@@ -1847,8 +1852,9 @@ sys_get_robust_list(int pid, struct robust_list_head __user * __user *head_ptr,
if (!p) if (!p)
goto err_unlock; goto err_unlock;
ret = -EPERM; ret = -EPERM;
if (euid != p->cred->euid && pcred = __task_cred(p);
euid != p->cred->uid && if (cred->euid != pcred->euid &&
cred->euid != pcred->uid &&
!capable(CAP_SYS_PTRACE)) !capable(CAP_SYS_PTRACE))
goto err_unlock; goto err_unlock;
head = p->robust_list; head = p->robust_list;
......
...@@ -135,7 +135,7 @@ compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr, ...@@ -135,7 +135,7 @@ compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr,
{ {
struct compat_robust_list_head __user *head; struct compat_robust_list_head __user *head;
unsigned long ret; unsigned long ret;
uid_t euid = current_euid(); const struct cred *cred = current_cred(), *pcred;
if (!futex_cmpxchg_enabled) if (!futex_cmpxchg_enabled)
return -ENOSYS; return -ENOSYS;
...@@ -151,8 +151,9 @@ compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr, ...@@ -151,8 +151,9 @@ compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr,
if (!p) if (!p)
goto err_unlock; goto err_unlock;
ret = -EPERM; ret = -EPERM;
if (euid != p->cred->euid && pcred = __task_cred(p);
euid != p->cred->uid && if (cred->euid != pcred->euid &&
cred->euid != pcred->uid &&
!capable(CAP_SYS_PTRACE)) !capable(CAP_SYS_PTRACE))
goto err_unlock; goto err_unlock;
head = p->compat_robust_list; head = p->compat_robust_list;
......
...@@ -115,7 +115,7 @@ int ptrace_check_attach(struct task_struct *child, int kill) ...@@ -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) 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? /* May we inspect the given task?
* This check is used both for attaching with ptrace * This check is used both for attaching with ptrace
...@@ -125,19 +125,23 @@ int __ptrace_may_access(struct task_struct *task, unsigned int mode) ...@@ -125,19 +125,23 @@ int __ptrace_may_access(struct task_struct *task, unsigned int mode)
* because setting up the necessary parent/child relationship * because setting up the necessary parent/child relationship
* or halting the specified task is impossible. * or halting the specified task is impossible.
*/ */
uid_t uid = cred->uid;
gid_t gid = cred->gid;
int dumpable = 0; int dumpable = 0;
/* Don't let security modules deny introspection */ /* Don't let security modules deny introspection */
if (task == current) if (task == current)
return 0; return 0;
if ((uid != tcred->euid || rcu_read_lock();
uid != tcred->suid || tcred = __task_cred(task);
uid != tcred->uid || if ((cred->uid != tcred->euid ||
gid != tcred->egid || cred->uid != tcred->suid ||
gid != tcred->sgid || cred->uid != tcred->uid ||
gid != tcred->gid) && !capable(CAP_SYS_PTRACE)) cred->gid != tcred->egid ||
cred->gid != tcred->sgid ||
cred->gid != tcred->gid) &&
!capable(CAP_SYS_PTRACE)) {
rcu_read_unlock();
return -EPERM; return -EPERM;
}
rcu_read_unlock();
smp_rmb(); smp_rmb();
if (task->mm) if (task->mm)
dumpable = get_dumpable(task->mm); dumpable = get_dumpable(task->mm);
......
...@@ -345,7 +345,9 @@ static inline struct task_group *task_group(struct task_struct *p) ...@@ -345,7 +345,9 @@ static inline struct task_group *task_group(struct task_struct *p)
struct task_group *tg; struct task_group *tg;
#ifdef CONFIG_USER_SCHED #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) #elif defined(CONFIG_CGROUP_SCHED)
tg = container_of(task_subsys_state(p, cpu_cgroup_subsys_id), tg = container_of(task_subsys_state(p, cpu_cgroup_subsys_id),
struct task_group, css); struct task_group, css);
...@@ -5121,6 +5123,22 @@ __setscheduler(struct rq *rq, struct task_struct *p, int policy, int prio) ...@@ -5121,6 +5123,22 @@ __setscheduler(struct rq *rq, struct task_struct *p, int policy, int prio)
set_load_weight(p); 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, static int __sched_setscheduler(struct task_struct *p, int policy,
struct sched_param *param, bool user) struct sched_param *param, bool user)
{ {
...@@ -5128,7 +5146,6 @@ static int __sched_setscheduler(struct task_struct *p, int policy, ...@@ -5128,7 +5146,6 @@ static int __sched_setscheduler(struct task_struct *p, int policy,
unsigned long flags; unsigned long flags;
const struct sched_class *prev_class = p->sched_class; const struct sched_class *prev_class = p->sched_class;
struct rq *rq; struct rq *rq;
uid_t euid;
/* may grab non-irq protected spin_locks */ /* may grab non-irq protected spin_locks */
BUG_ON(in_interrupt()); BUG_ON(in_interrupt());
...@@ -5181,9 +5198,7 @@ static int __sched_setscheduler(struct task_struct *p, int policy, ...@@ -5181,9 +5198,7 @@ static int __sched_setscheduler(struct task_struct *p, int policy,
return -EPERM; return -EPERM;
/* can't change other user's priorities */ /* can't change other user's priorities */
euid = current_euid(); if (!check_same_owner(p))
if (euid != p->cred->euid &&
euid != p->cred->uid)
return -EPERM; return -EPERM;
} }
...@@ -5394,7 +5409,6 @@ long sched_setaffinity(pid_t pid, const cpumask_t *in_mask) ...@@ -5394,7 +5409,6 @@ long sched_setaffinity(pid_t pid, const cpumask_t *in_mask)
cpumask_t cpus_allowed; cpumask_t cpus_allowed;
cpumask_t new_mask = *in_mask; cpumask_t new_mask = *in_mask;
struct task_struct *p; struct task_struct *p;
uid_t euid;
int retval; int retval;
get_online_cpus(); get_online_cpus();
...@@ -5415,11 +5429,8 @@ long sched_setaffinity(pid_t pid, const cpumask_t *in_mask) ...@@ -5415,11 +5429,8 @@ long sched_setaffinity(pid_t pid, const cpumask_t *in_mask)
get_task_struct(p); get_task_struct(p);
read_unlock(&tasklist_lock); read_unlock(&tasklist_lock);
euid = current_euid();
retval = -EPERM; retval = -EPERM;
if (euid != p->cred->euid && if (!check_same_owner(p) && !capable(CAP_SYS_NICE))
euid != p->cred->uid &&
!capable(CAP_SYS_NICE))
goto out_unlock; goto out_unlock;
retval = security_task_setscheduler(p, 0, NULL); retval = security_task_setscheduler(p, 0, NULL);
......
...@@ -177,6 +177,11 @@ int next_signal(struct sigpending *pending, sigset_t *mask) ...@@ -177,6 +177,11 @@ int next_signal(struct sigpending *pending, sigset_t *mask)
return sig; 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, static struct sigqueue *__sigqueue_alloc(struct task_struct *t, gfp_t flags,
int override_rlimit) int override_rlimit)
{ {
...@@ -184,11 +189,12 @@ static struct sigqueue *__sigqueue_alloc(struct task_struct *t, gfp_t flags, ...@@ -184,11 +189,12 @@ static struct sigqueue *__sigqueue_alloc(struct task_struct *t, gfp_t flags,
struct user_struct *user; struct user_struct *user;
/* /*
* In order to avoid problems with "switch_user()", we want to make * We won't get problems with the target's UID changing under us
* sure that the compiler doesn't re-load "t->user" * 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; user = __task_cred(t)->user;
barrier();
atomic_inc(&user->sigpending); atomic_inc(&user->sigpending);
if (override_rlimit || if (override_rlimit ||
atomic_read(&user->sigpending) <= atomic_read(&user->sigpending) <=
...@@ -562,12 +568,13 @@ static int rm_from_queue(unsigned long mask, struct sigpending *s) ...@@ -562,12 +568,13 @@ static int rm_from_queue(unsigned long mask, struct sigpending *s)
/* /*
* Bad permissions for sending the signal * 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, static int check_kill_permission(int sig, struct siginfo *info,
struct task_struct *t) struct task_struct *t)
{ {
const struct cred *cred = current_cred(), *tcred;
struct pid *sid; struct pid *sid;
uid_t uid, euid;
int error; int error;
if (!valid_signal(sig)) if (!valid_signal(sig))
...@@ -580,10 +587,11 @@ static int check_kill_permission(int sig, struct siginfo *info, ...@@ -580,10 +587,11 @@ static int check_kill_permission(int sig, struct siginfo *info,
if (error) if (error)
return error; return error;
uid = current_uid(); tcred = __task_cred(t);
euid = current_euid(); if ((cred->euid ^ tcred->suid) &&
if ((euid ^ t->cred->suid) && (euid ^ t->cred->uid) && (cred->euid ^ tcred->uid) &&
(uid ^ t->cred->suid) && (uid ^ t->cred->uid) && (cred->uid ^ tcred->suid) &&
(cred->uid ^ tcred->uid) &&
!capable(CAP_KILL)) { !capable(CAP_KILL)) {
switch (sig) { switch (sig) {
case SIGCONT: case SIGCONT:
...@@ -1011,6 +1019,10 @@ struct sighand_struct *lock_task_sighand(struct task_struct *tsk, unsigned long ...@@ -1011,6 +1019,10 @@ struct sighand_struct *lock_task_sighand(struct task_struct *tsk, unsigned long
return sighand; 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) int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
{ {
unsigned long flags; unsigned long flags;
...@@ -1032,8 +1044,8 @@ int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p) ...@@ -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 * __kill_pgrp_info() sends a signal to a process group: this is what the tty
* control characters do (^C, ^Z etc) * 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) int __kill_pgrp_info(int sig, struct siginfo *info, struct pid *pgrp)
{ {
struct task_struct *p = NULL; struct task_struct *p = NULL;
...@@ -1089,6 +1101,7 @@ int kill_pid_info_as_uid(int sig, struct siginfo *info, struct pid *pid, ...@@ -1089,6 +1101,7 @@ int kill_pid_info_as_uid(int sig, struct siginfo *info, struct pid *pid,
{ {
int ret = -EINVAL; int ret = -EINVAL;
struct task_struct *p; struct task_struct *p;
const struct cred *pcred;
if (!valid_signal(sig)) if (!valid_signal(sig))
return ret; return ret;
...@@ -1099,9 +1112,11 @@ int kill_pid_info_as_uid(int sig, struct siginfo *info, struct pid *pid, ...@@ -1099,9 +1112,11 @@ int kill_pid_info_as_uid(int sig, struct siginfo *info, struct pid *pid,
ret = -ESRCH; ret = -ESRCH;
goto out_unlock; goto out_unlock;
} }
if ((info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info))) pcred = __task_cred(p);
&& (euid != p->cred->suid) && (euid != p->cred->uid) if ((info == SEND_SIG_NOINFO ||
&& (uid != p->cred->suid) && (uid != p->cred->uid)) { (!is_si_special(info) && SI_FROMUSER(info))) &&
euid != pcred->suid && euid != pcred->uid &&
uid != pcred->suid && uid != pcred->uid) {
ret = -EPERM; ret = -EPERM;
goto out_unlock; goto out_unlock;
} }
...@@ -1372,10 +1387,9 @@ int do_notify_parent(struct task_struct *tsk, int sig) ...@@ -1372,10 +1387,9 @@ int do_notify_parent(struct task_struct *tsk, int sig)
*/ */
rcu_read_lock(); rcu_read_lock();
info.si_pid = task_pid_nr_ns(tsk, tsk->parent->nsproxy->pid_ns); info.si_pid = task_pid_nr_ns(tsk, tsk->parent->nsproxy->pid_ns);
info.si_uid = __task_cred(tsk)->uid;
rcu_read_unlock(); rcu_read_unlock();
info.si_uid = tsk->cred->uid;
thread_group_cputime(tsk, &cputime); thread_group_cputime(tsk, &cputime);
info.si_utime = cputime_to_jiffies(cputime.utime); info.si_utime = cputime_to_jiffies(cputime.utime);
info.si_stime = cputime_to_jiffies(cputime.stime); info.si_stime = cputime_to_jiffies(cputime.stime);
...@@ -1443,10 +1457,9 @@ static void do_notify_parent_cldstop(struct task_struct *tsk, int why) ...@@ -1443,10 +1457,9 @@ static void do_notify_parent_cldstop(struct task_struct *tsk, int why)
*/ */
rcu_read_lock(); rcu_read_lock();
info.si_pid = task_pid_nr_ns(tsk, tsk->parent->nsproxy->pid_ns); info.si_pid = task_pid_nr_ns(tsk, tsk->parent->nsproxy->pid_ns);
info.si_uid = __task_cred(tsk)->uid;
rcu_read_unlock(); rcu_read_unlock();
info.si_uid = tsk->cred->uid;
info.si_utime = cputime_to_clock_t(tsk->utime); info.si_utime = cputime_to_clock_t(tsk->utime);
info.si_stime = cputime_to_clock_t(tsk->stime); info.si_stime = cputime_to_clock_t(tsk->stime);
...@@ -1713,7 +1726,7 @@ static int ptrace_signal(int signr, siginfo_t *info, ...@@ -1713,7 +1726,7 @@ static int ptrace_signal(int signr, siginfo_t *info,
info->si_errno = 0; info->si_errno = 0;
info->si_code = SI_USER; info->si_code = SI_USER;
info->si_pid = task_pid_vnr(current->parent); 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. */ /* If the (new) signal is now blocked, requeue it. */
......
...@@ -112,14 +112,17 @@ EXPORT_SYMBOL(cad_pid); ...@@ -112,14 +112,17 @@ EXPORT_SYMBOL(cad_pid);
void (*pm_power_off_prepare)(void); 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) 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; int no_nice;
if (p->cred->uid != euid && if (pcred->uid != cred->euid &&
p->cred->euid != euid && pcred->euid != cred->euid && !capable(CAP_SYS_NICE)) {
!capable(CAP_SYS_NICE)) {
error = -EPERM; error = -EPERM;
goto out; goto out;
} }
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
*/ */
void bacct_add_tsk(struct taskstats *stats, struct task_struct *tsk) void bacct_add_tsk(struct taskstats *stats, struct task_struct *tsk)
{ {
const struct cred *tcred;
struct timespec uptime, ts; struct timespec uptime, ts;
u64 ac_etime; u64 ac_etime;
...@@ -53,10 +54,11 @@ void bacct_add_tsk(struct taskstats *stats, struct task_struct *tsk) ...@@ -53,10 +54,11 @@ void bacct_add_tsk(struct taskstats *stats, struct task_struct *tsk)
stats->ac_flag |= AXSIG; stats->ac_flag |= AXSIG;
stats->ac_nice = task_nice(tsk); stats->ac_nice = task_nice(tsk);
stats->ac_sched = tsk->policy; stats->ac_sched = tsk->policy;
stats->ac_uid = tsk->cred->uid;
stats->ac_gid = tsk->cred->gid;
stats->ac_pid = tsk->pid; stats->ac_pid = tsk->pid;
rcu_read_lock(); rcu_read_lock();
tcred = __task_cred(tsk);
stats->ac_uid = tcred->uid;
stats->ac_gid = tcred->gid;
stats->ac_ppid = pid_alive(tsk) ? stats->ac_ppid = pid_alive(tsk) ?
rcu_dereference(tsk->real_parent)->tgid : 0; rcu_dereference(tsk->real_parent)->tgid : 0;
rcu_read_unlock(); rcu_read_unlock();
......
...@@ -1110,7 +1110,7 @@ asmlinkage long sys_migrate_pages(pid_t pid, unsigned long maxnode, ...@@ -1110,7 +1110,7 @@ asmlinkage long sys_migrate_pages(pid_t pid, unsigned long maxnode,
const unsigned long __user *old_nodes, const unsigned long __user *old_nodes,
const unsigned long __user *new_nodes) const unsigned long __user *new_nodes)
{ {
struct cred *cred, *tcred; const struct cred *cred = current_cred(), *tcred;
struct mm_struct *mm; struct mm_struct *mm;
struct task_struct *task; struct task_struct *task;
nodemask_t old; nodemask_t old;
...@@ -1145,14 +1145,16 @@ asmlinkage long sys_migrate_pages(pid_t pid, unsigned long maxnode, ...@@ -1145,14 +1145,16 @@ asmlinkage long sys_migrate_pages(pid_t pid, unsigned long maxnode,
* capabilities, superuser privileges or the same * capabilities, superuser privileges or the same
* userid as the target process. * userid as the target process.
*/ */
cred = current->cred; rcu_read_lock();
tcred = task->cred; tcred = __task_cred(task);
if (cred->euid != tcred->suid && cred->euid != tcred->uid && if (cred->euid != tcred->suid && cred->euid != tcred->uid &&
cred->uid != tcred->suid && cred->uid != tcred->uid && cred->uid != tcred->suid && cred->uid != tcred->uid &&
!capable(CAP_SYS_NICE)) { !capable(CAP_SYS_NICE)) {
rcu_read_unlock();
err = -EPERM; err = -EPERM;
goto out; goto out;
} }
rcu_read_unlock();
task_nodes = cpuset_mems_allowed(task); task_nodes = cpuset_mems_allowed(task);
/* Is the user allowed to access the target nodes? */ /* Is the user allowed to access the target nodes? */
......
...@@ -1045,7 +1045,7 @@ asmlinkage long sys_move_pages(pid_t pid, unsigned long nr_pages, ...@@ -1045,7 +1045,7 @@ asmlinkage long sys_move_pages(pid_t pid, unsigned long nr_pages,
const int __user *nodes, const int __user *nodes,
int __user *status, int flags) int __user *status, int flags)
{ {
struct cred *cred, *tcred; const struct cred *cred = current_cred(), *tcred;
struct task_struct *task; struct task_struct *task;
struct mm_struct *mm; struct mm_struct *mm;
int err; int err;
...@@ -1076,14 +1076,16 @@ asmlinkage long sys_move_pages(pid_t pid, unsigned long nr_pages, ...@@ -1076,14 +1076,16 @@ asmlinkage long sys_move_pages(pid_t pid, unsigned long nr_pages,
* capabilities, superuser privileges or the same * capabilities, superuser privileges or the same
* userid as the target process. * userid as the target process.
*/ */
cred = current->cred; rcu_read_lock();
tcred = task->cred; tcred = __task_cred(task);
if (cred->euid != tcred->suid && cred->euid != tcred->uid && if (cred->euid != tcred->suid && cred->euid != tcred->uid &&
cred->uid != tcred->suid && cred->uid != tcred->uid && cred->uid != tcred->suid && cred->uid != tcred->uid &&
!capable(CAP_SYS_NICE)) { !capable(CAP_SYS_NICE)) {
rcu_read_unlock();
err = -EPERM; err = -EPERM;
goto out; goto out;
} }
rcu_read_unlock();
err = security_task_movememory(task); err = security_task_movememory(task);
if (err) if (err)
......
...@@ -298,9 +298,9 @@ static void dump_tasks(const struct mem_cgroup *mem) ...@@ -298,9 +298,9 @@ static void dump_tasks(const struct mem_cgroup *mem)
task_lock(p); task_lock(p);
printk(KERN_INFO "[%5d] %5d %5d %8lu %8lu %3d %3d %s\n", printk(KERN_INFO "[%5d] %5d %5d %8lu %8lu %3d %3d %s\n",
p->pid, p->cred->uid, p->tgid, p->mm->total_vm, p->pid, __task_cred(p)->uid, p->tgid,
get_mm_rss(p->mm), (int)task_cpu(p), p->oomkilladj, p->mm->total_vm, get_mm_rss(p->mm), (int)task_cpu(p),
p->comm); p->oomkilladj, p->comm);
task_unlock(p); task_unlock(p);
} while_each_thread(g, p); } while_each_thread(g, p);
} }
......
...@@ -51,10 +51,13 @@ EXPORT_SYMBOL(cap_netlink_recv); ...@@ -51,10 +51,13 @@ EXPORT_SYMBOL(cap_netlink_recv);
*/ */
int cap_capable(struct task_struct *tsk, int cap, int audit) int cap_capable(struct task_struct *tsk, int cap, int audit)
{ {
__u32 cap_raised;
/* Derived from include/linux/sched.h:capable. */ /* Derived from include/linux/sched.h:capable. */
if (cap_raised(tsk->cred->cap_effective, cap)) rcu_read_lock();
return 0; cap_raised = cap_raised(__task_cred(tsk)->cap_effective, cap);
return -EPERM; rcu_read_unlock();
return cap_raised ? 0 : -EPERM;
} }
int cap_settime(struct timespec *ts, struct timezone *tz) int cap_settime(struct timespec *ts, struct timezone *tz)
...@@ -66,34 +69,42 @@ int cap_settime(struct timespec *ts, struct timezone *tz) ...@@ -66,34 +69,42 @@ int cap_settime(struct timespec *ts, struct timezone *tz)
int cap_ptrace_may_access(struct task_struct *child, unsigned int mode) int cap_ptrace_may_access(struct task_struct *child, unsigned int mode)
{ {
/* Derived from arch/i386/kernel/ptrace.c:sys_ptrace. */ int ret = 0;
if (cap_issubset(child->cred->cap_permitted,
current->cred->cap_permitted)) rcu_read_lock();
return 0; if (!cap_issubset(child->cred->cap_permitted,
if (capable(CAP_SYS_PTRACE)) current->cred->cap_permitted) &&
return 0; !capable(CAP_SYS_PTRACE))
return -EPERM; ret = -EPERM;
rcu_read_unlock();
return ret;
} }
int cap_ptrace_traceme(struct task_struct *parent) int cap_ptrace_traceme(struct task_struct *parent)
{ {
if (cap_issubset(current->cred->cap_permitted, int ret = 0;
parent->cred->cap_permitted))
return 0; rcu_read_lock();
if (has_capability(parent, CAP_SYS_PTRACE)) if (!cap_issubset(current->cred->cap_permitted,
return 0; parent->cred->cap_permitted) &&
return -EPERM; !has_capability(parent, CAP_SYS_PTRACE))
ret = -EPERM;
rcu_read_unlock();
return ret;
} }
int cap_capget (struct task_struct *target, kernel_cap_t *effective, int cap_capget (struct task_struct *target, kernel_cap_t *effective,
kernel_cap_t *inheritable, kernel_cap_t *permitted) kernel_cap_t *inheritable, kernel_cap_t *permitted)
{ {
struct cred *cred = target->cred; const struct cred *cred;
/* Derived from kernel/capability.c:sys_capget. */ /* Derived from kernel/capability.c:sys_capget. */
rcu_read_lock();
cred = __task_cred(target);
*effective = cred->cap_effective; *effective = cred->cap_effective;
*inheritable = cred->cap_inheritable; *inheritable = cred->cap_inheritable;
*permitted = cred->cap_permitted; *permitted = cred->cap_permitted;
rcu_read_unlock();
return 0; return 0;
} }
...@@ -433,7 +444,7 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe) ...@@ -433,7 +444,7 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
int cap_bprm_secureexec (struct linux_binprm *bprm) int cap_bprm_secureexec (struct linux_binprm *bprm)
{ {
const struct cred *cred = current->cred; const struct cred *cred = current_cred();
if (cred->uid != 0) { if (cred->uid != 0) {
if (bprm->cap_effective) if (bprm->cap_effective)
...@@ -511,11 +522,11 @@ static inline void cap_emulate_setxuid (int old_ruid, int old_euid, ...@@ -511,11 +522,11 @@ static inline void cap_emulate_setxuid (int old_ruid, int old_euid,
if ((old_ruid == 0 || old_euid == 0 || old_suid == 0) && if ((old_ruid == 0 || old_euid == 0 || old_suid == 0) &&
(cred->uid != 0 && cred->euid != 0 && cred->suid != 0) && (cred->uid != 0 && cred->euid != 0 && cred->suid != 0) &&
!issecure(SECURE_KEEP_CAPS)) { !issecure(SECURE_KEEP_CAPS)) {
cap_clear (cred->cap_permitted); cap_clear(cred->cap_permitted);
cap_clear (cred->cap_effective); cap_clear(cred->cap_effective);
} }
if (old_euid == 0 && cred->euid != 0) { if (old_euid == 0 && cred->euid != 0) {
cap_clear (cred->cap_effective); cap_clear(cred->cap_effective);
} }
if (old_euid != 0 && cred->euid == 0) { if (old_euid != 0 && cred->euid == 0) {
cred->cap_effective = cred->cap_permitted; cred->cap_effective = cred->cap_permitted;
...@@ -582,9 +593,14 @@ int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, ...@@ -582,9 +593,14 @@ int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid,
*/ */
static int cap_safe_nice(struct task_struct *p) static int cap_safe_nice(struct task_struct *p)
{ {
if (!cap_issubset(p->cred->cap_permitted, int is_subset;
current->cred->cap_permitted) &&
!capable(CAP_SYS_NICE)) rcu_read_lock();
is_subset = cap_issubset(__task_cred(p)->cap_permitted,
current_cred()->cap_permitted);
rcu_read_unlock();
if (!is_subset && !capable(CAP_SYS_NICE))
return -EPERM; return -EPERM;
return 0; return 0;
} }
......
...@@ -22,13 +22,16 @@ int key_task_permission(const key_ref_t key_ref, ...@@ -22,13 +22,16 @@ int key_task_permission(const key_ref_t key_ref,
struct task_struct *context, struct task_struct *context,
key_perm_t perm) key_perm_t perm)
{ {
struct cred *cred = context->cred; const struct cred *cred;
struct key *key; struct key *key;
key_perm_t kperm; key_perm_t kperm;
int ret; int ret;
key = key_ref_to_ptr(key_ref); key = key_ref_to_ptr(key_ref);
rcu_read_lock();
cred = __task_cred(context);
/* use the second 8-bits of permissions for keys the caller owns */ /* use the second 8-bits of permissions for keys the caller owns */
if (key->uid == cred->fsuid) { if (key->uid == cred->fsuid) {
kperm = key->perm >> 16; kperm = key->perm >> 16;
...@@ -43,10 +46,7 @@ int key_task_permission(const key_ref_t key_ref, ...@@ -43,10 +46,7 @@ int key_task_permission(const key_ref_t key_ref,
goto use_these_perms; goto use_these_perms;
} }
spin_lock(&cred->lock);
ret = groups_search(cred->group_info, key->gid); ret = groups_search(cred->group_info, key->gid);
spin_unlock(&cred->lock);
if (ret) { if (ret) {
kperm = key->perm >> 8; kperm = key->perm >> 8;
goto use_these_perms; goto use_these_perms;
...@@ -57,6 +57,8 @@ int key_task_permission(const key_ref_t key_ref, ...@@ -57,6 +57,8 @@ int key_task_permission(const key_ref_t key_ref,
kperm = key->perm; kperm = key->perm;
use_these_perms: use_these_perms:
rcu_read_lock();
/* use the top 8-bits of permissions for keys the caller possesses /* use the top 8-bits of permissions for keys the caller possesses
* - possessor permissions are additive with other permissions * - possessor permissions are additive with other permissions
*/ */
......
...@@ -412,10 +412,13 @@ key_ref_t search_process_keyrings(struct key_type *type, ...@@ -412,10 +412,13 @@ key_ref_t search_process_keyrings(struct key_type *type,
struct task_struct *context) struct task_struct *context)
{ {
struct request_key_auth *rka; struct request_key_auth *rka;
struct cred *cred;
key_ref_t key_ref, ret, err; key_ref_t key_ref, ret, err;
might_sleep(); might_sleep();
cred = get_task_cred(context);
/* we want to return -EAGAIN or -ENOKEY if any of the keyrings were /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were
* searchable, but we failed to find a key or we found a negative key; * searchable, but we failed to find a key or we found a negative key;
* otherwise we want to return a sample error (probably -EACCES) if * otherwise we want to return a sample error (probably -EACCES) if
...@@ -428,9 +431,9 @@ key_ref_t search_process_keyrings(struct key_type *type, ...@@ -428,9 +431,9 @@ key_ref_t search_process_keyrings(struct key_type *type,
err = ERR_PTR(-EAGAIN); err = ERR_PTR(-EAGAIN);
/* search the thread keyring first */ /* search the thread keyring first */
if (context->cred->thread_keyring) { if (cred->thread_keyring) {
key_ref = keyring_search_aux( key_ref = keyring_search_aux(
make_key_ref(context->cred->thread_keyring, 1), make_key_ref(cred->thread_keyring, 1),
context, type, description, match); context, type, description, match);
if (!IS_ERR(key_ref)) if (!IS_ERR(key_ref))
goto found; goto found;
...@@ -495,9 +498,9 @@ key_ref_t search_process_keyrings(struct key_type *type, ...@@ -495,9 +498,9 @@ key_ref_t search_process_keyrings(struct key_type *type,
} }
} }
/* or search the user-session keyring */ /* or search the user-session keyring */
else if (context->cred->user->session_keyring) { else if (cred->user->session_keyring) {
key_ref = keyring_search_aux( key_ref = keyring_search_aux(
make_key_ref(context->cred->user->session_keyring, 1), make_key_ref(cred->user->session_keyring, 1),
context, type, description, match); context, type, description, match);
if (!IS_ERR(key_ref)) if (!IS_ERR(key_ref))
goto found; goto found;
...@@ -519,20 +522,20 @@ key_ref_t search_process_keyrings(struct key_type *type, ...@@ -519,20 +522,20 @@ key_ref_t search_process_keyrings(struct key_type *type,
* search the keyrings of the process mentioned there * search the keyrings of the process mentioned there
* - we don't permit access to request_key auth keys via this method * - we don't permit access to request_key auth keys via this method
*/ */
if (context->cred->request_key_auth && if (cred->request_key_auth &&
context == current && context == current &&
type != &key_type_request_key_auth type != &key_type_request_key_auth
) { ) {
/* defend against the auth key being revoked */ /* defend against the auth key being revoked */
down_read(&context->cred->request_key_auth->sem); down_read(&cred->request_key_auth->sem);
if (key_validate(context->cred->request_key_auth) == 0) { if (key_validate(cred->request_key_auth) == 0) {
rka = context->cred->request_key_auth->payload.data; rka = cred->request_key_auth->payload.data;
key_ref = search_process_keyrings(type, description, key_ref = search_process_keyrings(type, description,
match, rka->context); match, rka->context);
up_read(&context->cred->request_key_auth->sem); up_read(&cred->request_key_auth->sem);
if (!IS_ERR(key_ref)) if (!IS_ERR(key_ref))
goto found; goto found;
...@@ -549,7 +552,7 @@ key_ref_t search_process_keyrings(struct key_type *type, ...@@ -549,7 +552,7 @@ key_ref_t search_process_keyrings(struct key_type *type,
break; break;
} }
} else { } else {
up_read(&context->cred->request_key_auth->sem); up_read(&cred->request_key_auth->sem);
} }
} }
...@@ -557,6 +560,7 @@ key_ref_t search_process_keyrings(struct key_type *type, ...@@ -557,6 +560,7 @@ key_ref_t search_process_keyrings(struct key_type *type,
key_ref = ret ? ret : err; key_ref = ret ? ret : err;
found: found:
put_cred(cred);
return key_ref; return key_ref;
} /* end search_process_keyrings() */ } /* end search_process_keyrings() */
......
...@@ -95,13 +95,18 @@ extern void selnl_notify_setenforce(int val); ...@@ -95,13 +95,18 @@ extern void selnl_notify_setenforce(int val);
static int task_has_security(struct task_struct *tsk, static int task_has_security(struct task_struct *tsk,
u32 perms) u32 perms)
{ {
struct task_security_struct *tsec; const struct task_security_struct *tsec;
u32 sid = 0;
tsec = tsk->cred->security;
rcu_read_lock();
tsec = __task_cred(tsk)->security;
if (tsec)
sid = tsec->sid;
rcu_read_unlock();
if (!tsec) if (!tsec)
return -EACCES; return -EACCES;
return avc_has_perm(tsec->sid, SECINITSID_SECURITY, return avc_has_perm(sid, SECINITSID_SECURITY,
SECCLASS_SECURITY, perms, NULL); SECCLASS_SECURITY, perms, NULL);
} }
......
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
#include "smack.h" #include "smack.h"
#define task_security(task) (task_cred_xxx((task), security))
/* /*
* I hope these are the hokeyist lines of code in the module. Casey. * I hope these are the hokeyist lines of code in the module. Casey.
*/ */
...@@ -1012,7 +1014,7 @@ static void smack_cred_free(struct cred *cred) ...@@ -1012,7 +1014,7 @@ static void smack_cred_free(struct cred *cred)
*/ */
static int smack_task_setpgid(struct task_struct *p, pid_t pgid) static int smack_task_setpgid(struct task_struct *p, pid_t pgid)
{ {
return smk_curacc(p->cred->security, MAY_WRITE); return smk_curacc(task_security(p), MAY_WRITE);
} }
/** /**
...@@ -1023,7 +1025,7 @@ static int smack_task_setpgid(struct task_struct *p, pid_t pgid) ...@@ -1023,7 +1025,7 @@ static int smack_task_setpgid(struct task_struct *p, pid_t pgid)
*/ */
static int smack_task_getpgid(struct task_struct *p) static int smack_task_getpgid(struct task_struct *p)
{ {
return smk_curacc(p->cred->security, MAY_READ); return smk_curacc(task_security(p), MAY_READ);
} }
/** /**
...@@ -1034,7 +1036,7 @@ static int smack_task_getpgid(struct task_struct *p) ...@@ -1034,7 +1036,7 @@ static int smack_task_getpgid(struct task_struct *p)
*/ */
static int smack_task_getsid(struct task_struct *p) static int smack_task_getsid(struct task_struct *p)
{ {
return smk_curacc(p->cred->security, MAY_READ); return smk_curacc(task_security(p), MAY_READ);
} }
/** /**
...@@ -1046,7 +1048,7 @@ static int smack_task_getsid(struct task_struct *p) ...@@ -1046,7 +1048,7 @@ static int smack_task_getsid(struct task_struct *p)
*/ */
static void smack_task_getsecid(struct task_struct *p, u32 *secid) static void smack_task_getsecid(struct task_struct *p, u32 *secid)
{ {
*secid = smack_to_secid(p->cred->security); *secid = smack_to_secid(task_security(p));
} }
/** /**
...@@ -1062,7 +1064,7 @@ static int smack_task_setnice(struct task_struct *p, int nice) ...@@ -1062,7 +1064,7 @@ static int smack_task_setnice(struct task_struct *p, int nice)
rc = cap_task_setnice(p, nice); rc = cap_task_setnice(p, nice);
if (rc == 0) if (rc == 0)
rc = smk_curacc(p->cred->security, MAY_WRITE); rc = smk_curacc(task_security(p), MAY_WRITE);
return rc; return rc;
} }
...@@ -1079,7 +1081,7 @@ static int smack_task_setioprio(struct task_struct *p, int ioprio) ...@@ -1079,7 +1081,7 @@ static int smack_task_setioprio(struct task_struct *p, int ioprio)
rc = cap_task_setioprio(p, ioprio); rc = cap_task_setioprio(p, ioprio);
if (rc == 0) if (rc == 0)
rc = smk_curacc(p->cred->security, MAY_WRITE); rc = smk_curacc(task_security(p), MAY_WRITE);
return rc; return rc;
} }
...@@ -1091,7 +1093,7 @@ static int smack_task_setioprio(struct task_struct *p, int ioprio) ...@@ -1091,7 +1093,7 @@ static int smack_task_setioprio(struct task_struct *p, int ioprio)
*/ */
static int smack_task_getioprio(struct task_struct *p) static int smack_task_getioprio(struct task_struct *p)
{ {
return smk_curacc(p->cred->security, MAY_READ); return smk_curacc(task_security(p), MAY_READ);
} }
/** /**
...@@ -1109,7 +1111,7 @@ static int smack_task_setscheduler(struct task_struct *p, int policy, ...@@ -1109,7 +1111,7 @@ static int smack_task_setscheduler(struct task_struct *p, int policy,
rc = cap_task_setscheduler(p, policy, lp); rc = cap_task_setscheduler(p, policy, lp);
if (rc == 0) if (rc == 0)
rc = smk_curacc(p->cred->security, MAY_WRITE); rc = smk_curacc(task_security(p), MAY_WRITE);
return rc; return rc;
} }
...@@ -1121,7 +1123,7 @@ static int smack_task_setscheduler(struct task_struct *p, int policy, ...@@ -1121,7 +1123,7 @@ static int smack_task_setscheduler(struct task_struct *p, int policy,
*/ */
static int smack_task_getscheduler(struct task_struct *p) static int smack_task_getscheduler(struct task_struct *p)
{ {
return smk_curacc(p->cred->security, MAY_READ); return smk_curacc(task_security(p), MAY_READ);
} }
/** /**
...@@ -1132,7 +1134,7 @@ static int smack_task_getscheduler(struct task_struct *p) ...@@ -1132,7 +1134,7 @@ static int smack_task_getscheduler(struct task_struct *p)
*/ */
static int smack_task_movememory(struct task_struct *p) static int smack_task_movememory(struct task_struct *p)
{ {
return smk_curacc(p->cred->security, MAY_WRITE); return smk_curacc(task_security(p), MAY_WRITE);
} }
/** /**
...@@ -1155,13 +1157,13 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info, ...@@ -1155,13 +1157,13 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info,
* can write the receiver. * can write the receiver.
*/ */
if (secid == 0) if (secid == 0)
return smk_curacc(p->cred->security, MAY_WRITE); return smk_curacc(task_security(p), MAY_WRITE);
/* /*
* If the secid isn't 0 we're dealing with some USB IO * If the secid isn't 0 we're dealing with some USB IO
* specific behavior. This is not clean. For one thing * specific behavior. This is not clean. For one thing
* we can't take privilege into account. * we can't take privilege into account.
*/ */
return smk_access(smack_from_secid(secid), p->cred->security, MAY_WRITE); return smk_access(smack_from_secid(secid), task_security(p), MAY_WRITE);
} }
/** /**
...@@ -1174,7 +1176,7 @@ static int smack_task_wait(struct task_struct *p) ...@@ -1174,7 +1176,7 @@ static int smack_task_wait(struct task_struct *p)
{ {
int rc; int rc;
rc = smk_access(current->cred->security, p->cred->security, MAY_WRITE); rc = smk_access(current_security(), task_security(p), MAY_WRITE);
if (rc == 0) if (rc == 0)
return 0; return 0;
...@@ -1205,7 +1207,7 @@ static int smack_task_wait(struct task_struct *p) ...@@ -1205,7 +1207,7 @@ static int smack_task_wait(struct task_struct *p)
static void smack_task_to_inode(struct task_struct *p, struct inode *inode) static void smack_task_to_inode(struct task_struct *p, struct inode *inode)
{ {
struct inode_smack *isp = inode->i_security; struct inode_smack *isp = inode->i_security;
isp->smk_inode = p->cred->security; isp->smk_inode = task_security(p);
} }
/* /*
...@@ -2010,7 +2012,7 @@ static int smack_getprocattr(struct task_struct *p, char *name, char **value) ...@@ -2010,7 +2012,7 @@ static int smack_getprocattr(struct task_struct *p, char *name, char **value)
if (strcmp(name, "current") != 0) if (strcmp(name, "current") != 0)
return -EINVAL; return -EINVAL;
cp = kstrdup(p->cred->security, GFP_KERNEL); cp = kstrdup(task_security(p), GFP_KERNEL);
if (cp == NULL) if (cp == NULL)
return -ENOMEM; return -ENOMEM;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment