sched_setaffinity: add permission check

This commit is contained in:
Tomoki Shirasawa
2016-01-15 12:05:18 +09:00
parent 9bafd166e3
commit 172bf0a389

View File

@@ -4917,14 +4917,13 @@ SYSCALL_DECLARE(sched_setaffinity)
int tid = (int)ihk_mc_syscall_arg0(ctx); int tid = (int)ihk_mc_syscall_arg0(ctx);
size_t len = (size_t)ihk_mc_syscall_arg1(ctx); size_t len = (size_t)ihk_mc_syscall_arg1(ctx);
cpu_set_t *u_cpu_set = (cpu_set_t *)ihk_mc_syscall_arg2(ctx); cpu_set_t *u_cpu_set = (cpu_set_t *)ihk_mc_syscall_arg2(ctx);
cpu_set_t k_cpu_set, cpu_set; cpu_set_t k_cpu_set, cpu_set;
struct thread *thread; struct thread *thread;
int cpu_id; int cpu_id;
int empty_set = 1; int empty_set = 1;
unsigned long irqstate;
extern int num_processors; extern int num_processors;
kprintf("sched_setaffinity tid=%d len=%d set=%p\n", tid, len, u_cpu_set);
if (sizeof(k_cpu_set) > len) { if (sizeof(k_cpu_set) > len) {
memset(&k_cpu_set, 0, sizeof(k_cpu_set)); memset(&k_cpu_set, 0, sizeof(k_cpu_set));
} }
@@ -4956,47 +4955,35 @@ SYSCALL_DECLARE(sched_setaffinity)
tid = cpu_local_var(current)->tid; tid = cpu_local_var(current)->tid;
thread = cpu_local_var(current); thread = cpu_local_var(current);
cpu_id = ihk_mc_get_processor_id(); cpu_id = ihk_mc_get_processor_id();
irqstate = ihk_mc_spinlock_lock(&get_cpu_local_var(cpu_id)->runq_lock); hold_thread(thread);
goto found;
} }
else { else {
for (cpu_id = 0; cpu_id < num_processors; cpu_id++) { struct mcs_rwlock_node_irqsave lock;
irqstate = ihk_mc_spinlock_lock( struct thread *mythread = cpu_local_var(current);
&get_cpu_local_var(cpu_id)->runq_lock);
list_for_each_entry(thread, thread = find_thread(0, tid, &lock);
&get_cpu_local_var(cpu_id)->runq, sched_list) { if(!thread)
return -ESRCH;
if (thread->proc->pid && thread->tid == tid) { if(mythread->proc->euid != 0 &&
goto found; /* without unlocking runq_lock */ mythread->proc->euid != thread->proc->ruid &&
} mythread->proc->euid != thread->proc->euid){
} thread_unlock(thread, &lock);
return -EPERM;
ihk_mc_spinlock_unlock(&get_cpu_local_var(cpu_id)->runq_lock,
irqstate);
} }
hold_thread(thread);
thread_unlock(thread, &lock);
cpu_id = thread->cpu_id;
} }
kprintf("%s:%d Thread not found.\n", __FILE__, __LINE__);
return -ESRCH;
found:
memcpy(&thread->cpu_set, &cpu_set, sizeof(cpu_set)); memcpy(&thread->cpu_set, &cpu_set, sizeof(cpu_set));
if (!CPU_ISSET(cpu_id, &thread->cpu_set)) { if (!CPU_ISSET(cpu_id, &thread->cpu_set)) {
hold_thread(thread);
ihk_mc_spinlock_unlock(&get_cpu_local_var(cpu_id)->runq_lock, irqstate);
dkprintf("sched_setaffinity(): tid %d sched_request_migrate\n", dkprintf("sched_setaffinity(): tid %d sched_request_migrate\n",
cpu_local_var(current)->tid, cpu_id); cpu_local_var(current)->tid, cpu_id);
sched_request_migrate(cpu_id, thread); sched_request_migrate(cpu_id, thread);
release_thread(thread);
return 0;
}
else {
ihk_mc_spinlock_unlock(&get_cpu_local_var(cpu_id)->runq_lock, irqstate);
return 0;
} }
release_thread(thread);
return 0;
} }
// see linux-2.6.34.13/kernel/sched.c // see linux-2.6.34.13/kernel/sched.c
@@ -5005,38 +4992,37 @@ SYSCALL_DECLARE(sched_getaffinity)
int tid = (int)ihk_mc_syscall_arg0(ctx); int tid = (int)ihk_mc_syscall_arg0(ctx);
size_t len = (size_t)ihk_mc_syscall_arg1(ctx); size_t len = (size_t)ihk_mc_syscall_arg1(ctx);
cpu_set_t k_cpu_set, *u_cpu_set = (cpu_set_t *)ihk_mc_syscall_arg2(ctx); cpu_set_t k_cpu_set, *u_cpu_set = (cpu_set_t *)ihk_mc_syscall_arg2(ctx);
struct thread *thread;
int ret; int ret;
int found = 0;
int i;
unsigned long irqstate;
extern int num_processors;
if (!len) if (!len)
return -EINVAL; return -EINVAL;
len = MIN2(len, sizeof(k_cpu_set)); len = MIN2(len, sizeof(k_cpu_set));
if(tid == 0) if(tid == 0){
tid = cpu_local_var(current)->tid; thread = cpu_local_var(current);
hold_thread(thread);
}
else{
struct mcs_rwlock_node_irqsave lock;
struct thread *mythread = cpu_local_var(current);
for (i = 0; i < num_processors && !found; i++) { thread = find_thread(0, tid, &lock);
struct thread *thread; if(!thread)
irqstate = ihk_mc_spinlock_lock(&get_cpu_local_var(i)->runq_lock); return -ESRCH;
list_for_each_entry(thread, &get_cpu_local_var(i)->runq, sched_list) { if(mythread->proc->euid != 0 &&
if (thread->proc->pid && thread->tid == tid) { mythread->proc->euid != thread->proc->ruid &&
found = 1; mythread->proc->euid != thread->proc->euid){
memcpy(&k_cpu_set, &thread->cpu_set, sizeof(k_cpu_set)); thread_unlock(thread, &lock);
break; return -EPERM;
}
} }
ihk_mc_spinlock_unlock(&get_cpu_local_var(i)->runq_lock, irqstate); hold_thread(thread);
thread_unlock(thread, &lock);
} }
if (!found) {
kprintf("%s:%d Thread not found.\n", __FILE__, __LINE__); ret = copy_to_user(u_cpu_set, &thread->cpu_set, len);
return -ESRCH; release_thread(thread);
}
ret = copy_to_user(u_cpu_set, &k_cpu_set, len);
dkprintf("%s() ret: %d\n", __FUNCTION__, ret); dkprintf("%s() ret: %d\n", __FUNCTION__, ret);
if (ret < 0) if (ret < 0)
return ret; return ret;