The arg parameter is passed by value in Linux, but not in FreeBSD.
We still have to account for a copyin. Make sure the copyin will succeed by passing the FreeBSD syscall a pointer to userspace, albeit one that's automagically mapped into kernel space. Reported by: mr, Mitsuru IWASAKI <iwasaki@jp.FreeBSD.org> Tested by: Mitsuru IWASAKI <iwasaki@jp.FreeBSD.org>
This commit is contained in:
parent
88b1d98f31
commit
b18013f823
@ -224,9 +224,14 @@ linux_semctl(struct thread *td, struct linux_semctl_args *args)
|
||||
caddr_t sg;
|
||||
|
||||
sg = stackgap_init();
|
||||
|
||||
/* Make sure the arg parameter can be copied in. */
|
||||
unptr = stackgap_alloc(&sg, sizeof(union semun));
|
||||
bcopy(unptr, &args->arg, sizeof(union semun));
|
||||
|
||||
bsd_args.semid = args->semid;
|
||||
bsd_args.semnum = args->semnum;
|
||||
bsd_args.arg = (union semun *)&args->arg;
|
||||
bsd_args.arg = unptr;
|
||||
|
||||
switch (args->cmd) {
|
||||
case LINUX_IPC_RMID:
|
||||
@ -253,10 +258,8 @@ linux_semctl(struct thread *td, struct linux_semctl_args *args)
|
||||
sizeof(linux_semid));
|
||||
if (error)
|
||||
return (error);
|
||||
unptr = stackgap_alloc(&sg, sizeof(union semun));
|
||||
unptr->buf = stackgap_alloc(&sg, sizeof(struct semid_ds));
|
||||
linux_to_bsd_semid_ds(&linux_semid, unptr->buf);
|
||||
bsd_args.arg = unptr;
|
||||
return __semctl(td, &bsd_args);
|
||||
case LINUX_IPC_STAT:
|
||||
case LINUX_SEM_STAT:
|
||||
@ -264,9 +267,7 @@ linux_semctl(struct thread *td, struct linux_semctl_args *args)
|
||||
bsd_args.cmd = IPC_STAT;
|
||||
else
|
||||
bsd_args.cmd = SEM_STAT;
|
||||
unptr = stackgap_alloc(&sg, sizeof(union semun));
|
||||
unptr->buf = stackgap_alloc(&sg, sizeof(struct semid_ds));
|
||||
bsd_args.arg = unptr;
|
||||
error = __semctl(td, &bsd_args);
|
||||
if (error)
|
||||
return error;
|
||||
|
Loading…
Reference in New Issue
Block a user