Commit 6a1a1239 authored by Ernie Petrides's avatar Ernie Petrides Committed by David Mosberger

[PATCH] ia64: fixes for semtimedop() ia32-compat handling

Here are two fixes for the ia32-compatibility mode handling
for the new semtimedop() system call for the ia64 architecture.

The first problem was that treatment of user-mode calls to semtimedop()
with a NULL 4th (struct timespec *) parameter was inconsistent with the
behavior of the same executable on i386 and also with a natively compiled
ia64 binary.  A NULL 4th arg to semtimedop() should result in no timeout
being used (like a straight semop() call) rather than in an EFAULT error.

The second problem was that a legitimate semtimedop() with a timeout was
also resulting in an EFAULT because the fetch of the internal timespec
strucure by sys_semtimedop() from semtimedop32()'s kernel stack was
treated as an invalid user-data reference.  This requires temporarily
switching the addressing limit with set_fs(), further requiring that
appropriate parameter checking by performed prior to the switch.

The const qualifier was removed from the (struct compat_timespec *) arg
to semtimedop32() so that the call to get_compat_timespec() wouldn't
generate a compilation warning.
parent 7c19bf64
......@@ -1576,19 +1576,35 @@ shmctl32 (int first, int second, void *uptr)
return err;
}
extern int sem_ctls[];
#define sc_semopm (sem_ctls[2])
static long
semtimedop32(int semid, struct sembuf *tsems, int nsems,
const struct compat_timespec *timeout32)
semtimedop32(int semid, struct sembuf *tsops, int nsops,
struct compat_timespec *timeout32)
{
struct timespec t;
if (get_user (t.tv_sec, &timeout32->tv_sec) ||
get_user (t.tv_nsec, &timeout32->tv_nsec))
mm_segment_t oldfs;
long ret;
/* parameter checking precedence should mirror sys_semtimedop() */
if (nsops < 1 || semid < 0)
return -EINVAL;
if (nsops > sc_semopm)
return -E2BIG;
if (!access_ok(VERIFY_READ, tsops, nsops * sizeof(struct sembuf)) ||
get_compat_timespec(&t, timeout32))
return -EFAULT;
return sys_semtimedop(semid, tsems, nsems, &t);
oldfs = get_fs();
set_fs(KERNEL_DS);
ret = sys_semtimedop(semid, tsops, nsops, &t);
set_fs(oldfs);
return ret;
}
asmlinkage long
sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
sys32_ipc(u32 call, int first, int second, int third, u32 ptr, u32 fifth)
{
int version;
......@@ -1596,12 +1612,15 @@ sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
call &= 0xffff;
switch (call) {
case SEMTIMEDOP:
if (fifth)
return semtimedop32(first, (struct sembuf *)AA(ptr),
second, (struct compat_timespec *)AA(fifth));
/* else fall through for normal semop() */
case SEMOP:
/* struct sembuf is the same on 32 and 64bit :)) */
return sys_semtimedop(first, (struct sembuf *)AA(ptr), second, NULL);
case SEMTIMEDOP:
return semtimedop32(first, (struct sembuf *)AA(ptr), second,
(const struct compat_timespec *)AA(fifth));
return sys_semtimedop(first, (struct sembuf *)AA(ptr), second,
NULL);
case SEMGET:
return sys_semget(first, second, third);
case SEMCTL:
......
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