Commit fb377eb80c80339b580831a3c0fcce34a4c9d1ad
1 parent
78e05972c5
Exists in
smarc_imx_lf-5.15.y
and in
13 other branches
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>
Showing 3 changed files with 39 additions and 38 deletions Side-by-side Diff
arch/sparc/kernel/sys_sparc_64.c
| ... | ... | @@ -336,25 +336,28 @@ |
| 336 | 336 | { |
| 337 | 337 | long err; |
| 338 | 338 | |
| 339 | + if (!IS_ENABLED(CONFIG_SYSVIPC)) | |
| 340 | + return -ENOSYS; | |
| 341 | + | |
| 339 | 342 | /* No need for backward compatibility. We can start fresh... */ |
| 340 | 343 | if (call <= SEMTIMEDOP) { |
| 341 | 344 | switch (call) { |
| 342 | 345 | case SEMOP: |
| 343 | - err = sys_semtimedop(first, ptr, | |
| 344 | - (unsigned int)second, NULL); | |
| 346 | + err = ksys_semtimedop(first, ptr, | |
| 347 | + (unsigned int)second, NULL); | |
| 345 | 348 | goto out; |
| 346 | 349 | case SEMTIMEDOP: |
| 347 | - err = sys_semtimedop(first, ptr, (unsigned int)second, | |
| 350 | + err = ksys_semtimedop(first, ptr, (unsigned int)second, | |
| 348 | 351 | (const struct __kernel_timespec __user *) |
| 349 | - (unsigned long) fifth); | |
| 352 | + (unsigned long) fifth); | |
| 350 | 353 | goto out; |
| 351 | 354 | case SEMGET: |
| 352 | - err = sys_semget(first, (int)second, (int)third); | |
| 355 | + err = ksys_semget(first, (int)second, (int)third); | |
| 353 | 356 | goto out; |
| 354 | 357 | 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); | |
| 358 | 361 | goto out; |
| 359 | 362 | } |
| 360 | 363 | default: |
| 361 | 364 | |
| 362 | 365 | |
| 363 | 366 | |
| ... | ... | @@ -365,18 +368,18 @@ |
| 365 | 368 | if (call <= MSGCTL) { |
| 366 | 369 | switch (call) { |
| 367 | 370 | case MSGSND: |
| 368 | - err = sys_msgsnd(first, ptr, (size_t)second, | |
| 371 | + err = ksys_msgsnd(first, ptr, (size_t)second, | |
| 369 | 372 | (int)third); |
| 370 | 373 | goto out; |
| 371 | 374 | case MSGRCV: |
| 372 | - err = sys_msgrcv(first, ptr, (size_t)second, fifth, | |
| 375 | + err = ksys_msgrcv(first, ptr, (size_t)second, fifth, | |
| 373 | 376 | (int)third); |
| 374 | 377 | goto out; |
| 375 | 378 | case MSGGET: |
| 376 | - err = sys_msgget((key_t)first, (int)second); | |
| 379 | + err = ksys_msgget((key_t)first, (int)second); | |
| 377 | 380 | goto out; |
| 378 | 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 | 383 | goto out; |
| 381 | 384 | default: |
| 382 | 385 | err = -ENOSYS; |
| 383 | 386 | |
| 384 | 387 | |
| ... | ... | @@ -396,13 +399,13 @@ |
| 396 | 399 | goto out; |
| 397 | 400 | } |
| 398 | 401 | case SHMDT: |
| 399 | - err = sys_shmdt(ptr); | |
| 402 | + err = ksys_shmdt(ptr); | |
| 400 | 403 | goto out; |
| 401 | 404 | case SHMGET: |
| 402 | - err = sys_shmget(first, (size_t)second, (int)third); | |
| 405 | + err = ksys_shmget(first, (size_t)second, (int)third); | |
| 403 | 406 | goto out; |
| 404 | 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 | 409 | goto out; |
| 407 | 410 | default: |
| 408 | 411 | err = -ENOSYS; |
include/linux/syscalls.h
| ... | ... | @@ -1402,5 +1402,24 @@ |
| 1402 | 1402 | return old; |
| 1403 | 1403 | } |
| 1404 | 1404 | |
| 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 | + | |
| 1405 | 1424 | #endif |
ipc/util.h
| ... | ... | @@ -276,29 +276,7 @@ |
| 276 | 276 | *cmd &= ~IPC_64; |
| 277 | 277 | return version; |
| 278 | 278 | } |
| 279 | -#endif | |
| 280 | 279 | |
| 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 | |
| 302 | 280 | long compat_ksys_old_semctl(int semid, int semnum, int cmd, int arg); |
| 303 | 281 | long compat_ksys_old_msgctl(int msqid, int cmd, void __user *uptr); |
| 304 | 282 | long compat_ksys_msgrcv(int msqid, compat_uptr_t msgp, compat_ssize_t msgsz, |
| ... | ... | @@ -306,7 +284,8 @@ |
| 306 | 284 | long compat_ksys_msgsnd(int msqid, compat_uptr_t msgp, |
| 307 | 285 | compat_ssize_t msgsz, int msgflg); |
| 308 | 286 | long compat_ksys_old_shmctl(int shmid, int cmd, void __user *uptr); |
| 309 | -#endif /* CONFIG_COMPAT */ | |
| 287 | + | |
| 288 | +#endif | |
| 310 | 289 | |
| 311 | 290 | #endif |