Commit fb377eb80c80339b580831a3c0fcce34a4c9d1ad

Authored by Arnd Bergmann
1 parent 78e05972c5

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
... ... @@ -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