Le 17/08/2020 à 17:23, Filip Bozuta a écrit : > The implementations of syscalls 'semop()' and 'semtimedop()' in > file 'syscall.c' use function 'target_to_host_sembuf()' to convert > values of 'struct sembuf' from host to target. However, before this > conversion it should be check whether the number of semaphore operations > 'nsops' is not bigger than maximum allowed semaphor operations per > syscall: 'SEMOPM'. In these cases, errno 'E2BIG' ("Arg list too long") > should be set. But the implementation will set errno 'EFAULT' ("Bad address") > in this case since the conversion from target to host in this case fails. > > This was confirmed with the LTP test for 'semop()' ('ipc/semop/semop02') in > test case where 'nsops' is greater than SEMOPM with unaproppriate errno > EFAULT: > > semop02.c:130: FAIL: semop failed unexpectedly; expected: E2BIG: EFAULT (14) > > This patch changes this by adding a check whether 'nsops' is bigger than > 'SEMOPM' before the conversion function 'target_to_host_sembuf()' is called. > After the changes from this patch, the test works fine along with the other > LTP testcases for 'semop()'): > > semop02.c:126: PASS: semop failed as expected: E2BIG (7) > > Implementation notes: > > A target value ('TARGET_SEMOPM') was added for 'SEMOPM' as to be sure > in case the value is not available for some targets. > > Signed-off-by: Filip Bozuta <filip.boz...@syrmia.com> > --- > linux-user/syscall.c | 12 ++++++++++-- > linux-user/syscall_defs.h | 2 ++ > 2 files changed, 12 insertions(+), 2 deletions(-) > > diff --git a/linux-user/syscall.c b/linux-user/syscall.c > index 1211e759c2..70b172740c 100644 > --- a/linux-user/syscall.c > +++ b/linux-user/syscall.c > @@ -3904,7 +3904,7 @@ static inline abi_long do_semtimedop(int semid, > unsigned nsops, > abi_long timeout) > { > - struct sembuf sops[nsops]; > + struct sembuf *sops = NULL;
No need to set it to NULL. > struct timespec ts, *pts = NULL; > abi_long ret; > > @@ -3915,8 +3915,15 @@ static inline abi_long do_semtimedop(int semid, > } > } > > - if (target_to_host_sembuf(sops, ptr, nsops)) > + if (nsops > TARGET_SEMOPM) { > + return -TARGET_E2BIG; > + } > + > + sops = g_new(struct sembuf, nsops); > + > + if (target_to_host_sembuf(sops, ptr, nsops)) { Add: g_free(sops); > return -TARGET_EFAULT; > + } > > ret = -TARGET_ENOSYS; > #ifdef __NR_semtimedop Thanks, Laurent