Skip to content

Commit fb377eb

Browse files
committed
ipc: fix sparc64 ipc() wrapper
Matt bisected a sparc64 specific issue with semctl, shmctl and msgctl to a commit from my y2038 series in linux-5.1, as I missed the custom sys_ipc() wrapper that sparc64 uses in place of the generic version that I patched. The problem is that the sys_{sem,shm,msg}ctl() functions in the kernel now do not allow being called with the IPC_64 flag any more, resulting in a -EINVAL error when they don't recognize the command. Instead, the correct way to do this now is to call the internal ksys_old_{sem,shm,msg}ctl() functions to select the API version. As we generally move towards these functions anyway, change all of sparc_ipc() to consistently use those in place of the sys_*() versions, and move the required ksys_*() declarations into linux/syscalls.h The IS_ENABLED(CONFIG_SYSVIPC) check is required to avoid link errors when ipc is disabled. Reported-by: Matt Turner <[email protected]> Fixes: 275f221 ("ipc: rename old-style shmctl/semctl/msgctl syscalls") Cc: [email protected] Tested-by: Matt Turner <[email protected]> Tested-by: Anatoly Pugachev <[email protected]> Signed-off-by: Arnd Bergmann <[email protected]>
1 parent 78e0597 commit fb377eb

File tree

3 files changed

+39
-38
lines changed

3 files changed

+39
-38
lines changed

arch/sparc/kernel/sys_sparc_64.c

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -336,25 +336,28 @@ SYSCALL_DEFINE6(sparc_ipc, unsigned int, call, int, first, unsigned long, second
336336
{
337337
long err;
338338

339+
if (!IS_ENABLED(CONFIG_SYSVIPC))
340+
return -ENOSYS;
341+
339342
/* No need for backward compatibility. We can start fresh... */
340343
if (call <= SEMTIMEDOP) {
341344
switch (call) {
342345
case SEMOP:
343-
err = sys_semtimedop(first, ptr,
344-
(unsigned int)second, NULL);
346+
err = ksys_semtimedop(first, ptr,
347+
(unsigned int)second, NULL);
345348
goto out;
346349
case SEMTIMEDOP:
347-
err = sys_semtimedop(first, ptr, (unsigned int)second,
350+
err = ksys_semtimedop(first, ptr, (unsigned int)second,
348351
(const struct __kernel_timespec __user *)
349-
(unsigned long) fifth);
352+
(unsigned long) fifth);
350353
goto out;
351354
case SEMGET:
352-
err = sys_semget(first, (int)second, (int)third);
355+
err = ksys_semget(first, (int)second, (int)third);
353356
goto out;
354357
case SEMCTL: {
355-
err = sys_semctl(first, second,
356-
(int)third | IPC_64,
357-
(unsigned long) ptr);
358+
err = ksys_old_semctl(first, second,
359+
(int)third | IPC_64,
360+
(unsigned long) ptr);
358361
goto out;
359362
}
360363
default:
@@ -365,18 +368,18 @@ SYSCALL_DEFINE6(sparc_ipc, unsigned int, call, int, first, unsigned long, second
365368
if (call <= MSGCTL) {
366369
switch (call) {
367370
case MSGSND:
368-
err = sys_msgsnd(first, ptr, (size_t)second,
371+
err = ksys_msgsnd(first, ptr, (size_t)second,
369372
(int)third);
370373
goto out;
371374
case MSGRCV:
372-
err = sys_msgrcv(first, ptr, (size_t)second, fifth,
375+
err = ksys_msgrcv(first, ptr, (size_t)second, fifth,
373376
(int)third);
374377
goto out;
375378
case MSGGET:
376-
err = sys_msgget((key_t)first, (int)second);
379+
err = ksys_msgget((key_t)first, (int)second);
377380
goto out;
378381
case MSGCTL:
379-
err = sys_msgctl(first, (int)second | IPC_64, ptr);
382+
err = ksys_old_msgctl(first, (int)second | IPC_64, ptr);
380383
goto out;
381384
default:
382385
err = -ENOSYS;
@@ -396,13 +399,13 @@ SYSCALL_DEFINE6(sparc_ipc, unsigned int, call, int, first, unsigned long, second
396399
goto out;
397400
}
398401
case SHMDT:
399-
err = sys_shmdt(ptr);
402+
err = ksys_shmdt(ptr);
400403
goto out;
401404
case SHMGET:
402-
err = sys_shmget(first, (size_t)second, (int)third);
405+
err = ksys_shmget(first, (size_t)second, (int)third);
403406
goto out;
404407
case SHMCTL:
405-
err = sys_shmctl(first, (int)second | IPC_64, ptr);
408+
err = ksys_old_shmctl(first, (int)second | IPC_64, ptr);
406409
goto out;
407410
default:
408411
err = -ENOSYS;

include/linux/syscalls.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1402,4 +1402,23 @@ static inline unsigned int ksys_personality(unsigned int personality)
14021402
return old;
14031403
}
14041404

1405+
/* for __ARCH_WANT_SYS_IPC */
1406+
long ksys_semtimedop(int semid, struct sembuf __user *tsops,
1407+
unsigned int nsops,
1408+
const struct __kernel_timespec __user *timeout);
1409+
long ksys_semget(key_t key, int nsems, int semflg);
1410+
long ksys_old_semctl(int semid, int semnum, int cmd, unsigned long arg);
1411+
long ksys_msgget(key_t key, int msgflg);
1412+
long ksys_old_msgctl(int msqid, int cmd, struct msqid_ds __user *buf);
1413+
long ksys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz,
1414+
long msgtyp, int msgflg);
1415+
long ksys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz,
1416+
int msgflg);
1417+
long ksys_shmget(key_t key, size_t size, int shmflg);
1418+
long ksys_shmdt(char __user *shmaddr);
1419+
long ksys_old_shmctl(int shmid, int cmd, struct shmid_ds __user *buf);
1420+
long compat_ksys_semtimedop(int semid, struct sembuf __user *tsems,
1421+
unsigned int nsops,
1422+
const struct old_timespec32 __user *timeout);
1423+
14051424
#endif

ipc/util.h

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -276,36 +276,15 @@ static inline int compat_ipc_parse_version(int *cmd)
276276
*cmd &= ~IPC_64;
277277
return version;
278278
}
279-
#endif
280279

281-
/* for __ARCH_WANT_SYS_IPC */
282-
long ksys_semtimedop(int semid, struct sembuf __user *tsops,
283-
unsigned int nsops,
284-
const struct __kernel_timespec __user *timeout);
285-
long ksys_semget(key_t key, int nsems, int semflg);
286-
long ksys_old_semctl(int semid, int semnum, int cmd, unsigned long arg);
287-
long ksys_msgget(key_t key, int msgflg);
288-
long ksys_old_msgctl(int msqid, int cmd, struct msqid_ds __user *buf);
289-
long ksys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz,
290-
long msgtyp, int msgflg);
291-
long ksys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz,
292-
int msgflg);
293-
long ksys_shmget(key_t key, size_t size, int shmflg);
294-
long ksys_shmdt(char __user *shmaddr);
295-
long ksys_old_shmctl(int shmid, int cmd, struct shmid_ds __user *buf);
296-
297-
/* for CONFIG_ARCH_WANT_OLD_COMPAT_IPC */
298-
long compat_ksys_semtimedop(int semid, struct sembuf __user *tsems,
299-
unsigned int nsops,
300-
const struct old_timespec32 __user *timeout);
301-
#ifdef CONFIG_COMPAT
302280
long compat_ksys_old_semctl(int semid, int semnum, int cmd, int arg);
303281
long compat_ksys_old_msgctl(int msqid, int cmd, void __user *uptr);
304282
long compat_ksys_msgrcv(int msqid, compat_uptr_t msgp, compat_ssize_t msgsz,
305283
compat_long_t msgtyp, int msgflg);
306284
long compat_ksys_msgsnd(int msqid, compat_uptr_t msgp,
307285
compat_ssize_t msgsz, int msgflg);
308286
long compat_ksys_old_shmctl(int shmid, int cmd, void __user *uptr);
309-
#endif /* CONFIG_COMPAT */
287+
288+
#endif
310289

311290
#endif

0 commit comments

Comments
 (0)