summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2019-09-05 10:48:38 -0400
committerArnd Bergmann <arnd@arndb.de>2019-09-07 15:42:25 -0400
commitfb377eb80c80339b580831a3c0fcce34a4c9d1ad (patch)
treeec74cca6e1cb4ccd8516491822bb76fd9ff94996
parent78e05972c5e6c8e9ca4c00ccc6985409da69f904 (diff)
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 <mattst88@gmail.com> Fixes: 275f22148e87 ("ipc: rename old-style shmctl/semctl/msgctl syscalls") Cc: stable@vger.kernel.org Tested-by: Matt Turner <mattst88@gmail.com> Tested-by: Anatoly Pugachev <matorola@gmail.com> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r--arch/sparc/kernel/sys_sparc_64.c33
-rw-r--r--include/linux/syscalls.h19
-rw-r--r--ipc/util.h25
3 files changed, 39 insertions, 38 deletions
diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c
index ccc88926bc00..9f41a6f5a032 100644
--- a/arch/sparc/kernel/sys_sparc_64.c
+++ b/arch/sparc/kernel/sys_sparc_64.c
@@ -336,25 +336,28 @@ SYSCALL_DEFINE6(sparc_ipc, unsigned int, call, int, first, unsigned long, second
336{ 336{
337 long err; 337 long err;
338 338
339 if (!IS_ENABLED(CONFIG_SYSVIPC))
340 return -ENOSYS;
341
339 /* No need for backward compatibility. We can start fresh... */ 342 /* No need for backward compatibility. We can start fresh... */
340 if (call <= SEMTIMEDOP) { 343 if (call <= SEMTIMEDOP) {
341 switch (call) { 344 switch (call) {
342 case SEMOP: 345 case SEMOP:
343 err = sys_semtimedop(first, ptr, 346 err = ksys_semtimedop(first, ptr,
344 (unsigned int)second, NULL); 347 (unsigned int)second, NULL);
345 goto out; 348 goto out;
346 case SEMTIMEDOP: 349 case SEMTIMEDOP:
347 err = sys_semtimedop(first, ptr, (unsigned int)second, 350 err = ksys_semtimedop(first, ptr, (unsigned int)second,
348 (const struct __kernel_timespec __user *) 351 (const struct __kernel_timespec __user *)
349 (unsigned long) fifth); 352 (unsigned long) fifth);
350 goto out; 353 goto out;
351 case SEMGET: 354 case SEMGET:
352 err = sys_semget(first, (int)second, (int)third); 355 err = ksys_semget(first, (int)second, (int)third);
353 goto out; 356 goto out;
354 case SEMCTL: { 357 case SEMCTL: {
355 err = sys_semctl(first, second, 358 err = ksys_old_semctl(first, second,
356 (int)third | IPC_64, 359 (int)third | IPC_64,
357 (unsigned long) ptr); 360 (unsigned long) ptr);
358 goto out; 361 goto out;
359 } 362 }
360 default: 363 default:
@@ -365,18 +368,18 @@ SYSCALL_DEFINE6(sparc_ipc, unsigned int, call, int, first, unsigned long, second
365 if (call <= MSGCTL) { 368 if (call <= MSGCTL) {
366 switch (call) { 369 switch (call) {
367 case MSGSND: 370 case MSGSND:
368 err = sys_msgsnd(first, ptr, (size_t)second, 371 err = ksys_msgsnd(first, ptr, (size_t)second,
369 (int)third); 372 (int)third);
370 goto out; 373 goto out;
371 case MSGRCV: 374 case MSGRCV:
372 err = sys_msgrcv(first, ptr, (size_t)second, fifth, 375 err = ksys_msgrcv(first, ptr, (size_t)second, fifth,
373 (int)third); 376 (int)third);
374 goto out; 377 goto out;
375 case MSGGET: 378 case MSGGET:
376 err = sys_msgget((key_t)first, (int)second); 379 err = ksys_msgget((key_t)first, (int)second);
377 goto out; 380 goto out;
378 case MSGCTL: 381 case MSGCTL:
379 err = sys_msgctl(first, (int)second | IPC_64, ptr); 382 err = ksys_old_msgctl(first, (int)second | IPC_64, ptr);
380 goto out; 383 goto out;
381 default: 384 default:
382 err = -ENOSYS; 385 err = -ENOSYS;
@@ -396,13 +399,13 @@ SYSCALL_DEFINE6(sparc_ipc, unsigned int, call, int, first, unsigned long, second
396 goto out; 399 goto out;
397 } 400 }
398 case SHMDT: 401 case SHMDT:
399 err = sys_shmdt(ptr); 402 err = ksys_shmdt(ptr);
400 goto out; 403 goto out;
401 case SHMGET: 404 case SHMGET:
402 err = sys_shmget(first, (size_t)second, (int)third); 405 err = ksys_shmget(first, (size_t)second, (int)third);
403 goto out; 406 goto out;
404 case SHMCTL: 407 case SHMCTL:
405 err = sys_shmctl(first, (int)second | IPC_64, ptr); 408 err = ksys_old_shmctl(first, (int)second | IPC_64, ptr);
406 goto out; 409 goto out;
407 default: 410 default:
408 err = -ENOSYS; 411 err = -ENOSYS;
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 88145da7d140..f7c561c4dcdd 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -1402,4 +1402,23 @@ static inline unsigned int ksys_personality(unsigned int personality)
1402 return old; 1402 return old;
1403} 1403}
1404 1404
1405/* for __ARCH_WANT_SYS_IPC */
1406long ksys_semtimedop(int semid, struct sembuf __user *tsops,
1407 unsigned int nsops,
1408 const struct __kernel_timespec __user *timeout);
1409long ksys_semget(key_t key, int nsems, int semflg);
1410long ksys_old_semctl(int semid, int semnum, int cmd, unsigned long arg);
1411long ksys_msgget(key_t key, int msgflg);
1412long ksys_old_msgctl(int msqid, int cmd, struct msqid_ds __user *buf);
1413long ksys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz,
1414 long msgtyp, int msgflg);
1415long ksys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz,
1416 int msgflg);
1417long ksys_shmget(key_t key, size_t size, int shmflg);
1418long ksys_shmdt(char __user *shmaddr);
1419long ksys_old_shmctl(int shmid, int cmd, struct shmid_ds __user *buf);
1420long compat_ksys_semtimedop(int semid, struct sembuf __user *tsems,
1421 unsigned int nsops,
1422 const struct old_timespec32 __user *timeout);
1423
1405#endif 1424#endif
diff --git a/ipc/util.h b/ipc/util.h
index 0fcf8e719b76..5766c61aed0e 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -276,29 +276,7 @@ static inline int compat_ipc_parse_version(int *cmd)
276 *cmd &= ~IPC_64; 276 *cmd &= ~IPC_64;
277 return version; 277 return version;
278} 278}
279#endif
280 279
281/* for __ARCH_WANT_SYS_IPC */
282long ksys_semtimedop(int semid, struct sembuf __user *tsops,
283 unsigned int nsops,
284 const struct __kernel_timespec __user *timeout);
285long ksys_semget(key_t key, int nsems, int semflg);
286long ksys_old_semctl(int semid, int semnum, int cmd, unsigned long arg);
287long ksys_msgget(key_t key, int msgflg);
288long ksys_old_msgctl(int msqid, int cmd, struct msqid_ds __user *buf);
289long ksys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz,
290 long msgtyp, int msgflg);
291long ksys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz,
292 int msgflg);
293long ksys_shmget(key_t key, size_t size, int shmflg);
294long ksys_shmdt(char __user *shmaddr);
295long ksys_old_shmctl(int shmid, int cmd, struct shmid_ds __user *buf);
296
297/* for CONFIG_ARCH_WANT_OLD_COMPAT_IPC */
298long compat_ksys_semtimedop(int semid, struct sembuf __user *tsems,
299 unsigned int nsops,
300 const struct old_timespec32 __user *timeout);
301#ifdef CONFIG_COMPAT
302long compat_ksys_old_semctl(int semid, int semnum, int cmd, int arg); 280long compat_ksys_old_semctl(int semid, int semnum, int cmd, int arg);
303long compat_ksys_old_msgctl(int msqid, int cmd, void __user *uptr); 281long compat_ksys_old_msgctl(int msqid, int cmd, void __user *uptr);
304long compat_ksys_msgrcv(int msqid, compat_uptr_t msgp, compat_ssize_t msgsz, 282long compat_ksys_msgrcv(int msqid, compat_uptr_t msgp, compat_ssize_t msgsz,
@@ -306,6 +284,7 @@ long compat_ksys_msgrcv(int msqid, compat_uptr_t msgp, compat_ssize_t msgsz,
306long compat_ksys_msgsnd(int msqid, compat_uptr_t msgp, 284long compat_ksys_msgsnd(int msqid, compat_uptr_t msgp,
307 compat_ssize_t msgsz, int msgflg); 285 compat_ssize_t msgsz, int msgflg);
308long compat_ksys_old_shmctl(int shmid, int cmd, void __user *uptr); 286long compat_ksys_old_shmctl(int shmid, int cmd, void __user *uptr);
309#endif /* CONFIG_COMPAT */ 287
288#endif
310 289
311#endif 290#endif