Commit 4ba4986a authored by Jan Kiszka's avatar Jan Kiszka Committed by Philippe Gerum

cobalt/posix/sem: Fix sem_open for preexisting semaphores

We missed to create and copy the shadow into userspace in case a
preexisting semaphore was opened in process that didn't created it. Was
biting us in pshared setups, but also when the previous owner died
before destroying a named semaphore.
Reported-by: 's avatarPaal Tamas <paal_to@freemail.hu>
Signed-off-by: Jan Kiszka's avatarJan Kiszka <jan.kiszka@siemens.com>
parent 6d71a43e
......@@ -95,6 +95,8 @@ sem_open(struct cobalt_process *process,
xnlock_put_irqrestore(&nklock, s);
goto retry_bind;
}
__cobalt_sem_shadow_init(sem, COBALT_NAMED_SEM_MAGIC, &shadow);
break;
case -EWOULDBLOCK:
......@@ -112,10 +114,6 @@ sem_open(struct cobalt_process *process,
return ERR_PTR(rc);
}
if (cobalt_copy_to_user(ushadow, &shadow, sizeof(shadow))) {
__cobalt_sem_destroy(shadow.handle);
return ERR_PTR(-EFAULT);
}
sem->pathname = filename;
handle = shadow.handle;
break;
......@@ -124,6 +122,11 @@ sem_open(struct cobalt_process *process,
return ERR_PTR(rc);
}
if (cobalt_copy_to_user(ushadow, &shadow, sizeof(shadow))) {
__cobalt_sem_destroy(handle);
return ERR_PTR(-EFAULT);
}
u = xnmalloc(sizeof(*u));
if (u == NULL) {
__cobalt_sem_destroy(handle);
......
......@@ -153,13 +153,11 @@ __cobalt_sem_init(const char *name, struct cobalt_sem_shadow *sm,
sem->refs = name ? 2 : 1;
sem->pathname = NULL;
sm->magic = name ? COBALT_NAMED_SEM_MAGIC : COBALT_SEM_MAGIC;
sm->handle = sem->resnode.handle;
sm->state_offset = cobalt_umm_offset(&sys_ppd->umm, state);
if (flags & SEM_PSHARED)
sm->state_offset = -sm->state_offset;
xnlock_put_irqrestore(&nklock, s);
__cobalt_sem_shadow_init(sem,
name ? COBALT_NAMED_SEM_MAGIC : COBALT_SEM_MAGIC, sm);
trace_cobalt_psem_init(name ?: "anon",
sem->resnode.handle, flags, value);
......@@ -176,6 +174,21 @@ out:
return ERR_PTR(ret);
}
void __cobalt_sem_shadow_init(struct cobalt_sem *sem, __u32 magic,
struct cobalt_sem_shadow *sm)
{
__u32 flags = sem->state->flags;
struct cobalt_ppd *sys_ppd;
sys_ppd = cobalt_ppd_get(!!(flags & SEM_PSHARED));
sm->magic = magic;
sm->handle = sem->resnode.handle;
sm->state_offset = cobalt_umm_offset(&sys_ppd->umm, sem->state);
if (sem->state->flags & SEM_PSHARED)
sm->state_offset = -sm->state_offset;
}
static int sem_destroy(struct cobalt_sem_shadow *sm)
{
struct cobalt_sem *sem;
......
......@@ -76,6 +76,9 @@ struct cobalt_sem *
__cobalt_sem_init(const char *name, struct cobalt_sem_shadow *sem,
int flags, unsigned value);
void __cobalt_sem_shadow_init(struct cobalt_sem *sem, __u32 magic,
struct cobalt_sem_shadow *sm);
COBALT_SYSCALL_DECL(sem_init,
(struct cobalt_sem_shadow __user *u_sem,
int flags, unsigned value));
......
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