root/ipc/syscall.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ksys_ipc
  2. SYSCALL_DEFINE6
  3. compat_ksys_ipc
  4. COMPAT_SYSCALL_DEFINE6

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * sys_ipc() is the old de-multiplexer for the SysV IPC calls.
   4  *
   5  * This is really horribly ugly, and new architectures should just wire up
   6  * the individual syscalls instead.
   7  */
   8 #include <linux/unistd.h>
   9 #include <linux/syscalls.h>
  10 #include <linux/security.h>
  11 #include <linux/ipc_namespace.h>
  12 #include "util.h"
  13 
  14 #ifdef __ARCH_WANT_SYS_IPC
  15 #include <linux/errno.h>
  16 #include <linux/ipc.h>
  17 #include <linux/shm.h>
  18 #include <linux/uaccess.h>
  19 
  20 int ksys_ipc(unsigned int call, int first, unsigned long second,
  21         unsigned long third, void __user * ptr, long fifth)
  22 {
  23         int version, ret;
  24 
  25         version = call >> 16; /* hack for backward compatibility */
  26         call &= 0xffff;
  27 
  28         switch (call) {
  29         case SEMOP:
  30                 return ksys_semtimedop(first, (struct sembuf __user *)ptr,
  31                                        second, NULL);
  32         case SEMTIMEDOP:
  33                 if (IS_ENABLED(CONFIG_64BIT) || !IS_ENABLED(CONFIG_64BIT_TIME))
  34                         return ksys_semtimedop(first, ptr, second,
  35                                 (const struct __kernel_timespec __user *)fifth);
  36                 else if (IS_ENABLED(CONFIG_COMPAT_32BIT_TIME))
  37                         return compat_ksys_semtimedop(first, ptr, second,
  38                                 (const struct old_timespec32 __user *)fifth);
  39                 else
  40                         return -ENOSYS;
  41 
  42         case SEMGET:
  43                 return ksys_semget(first, second, third);
  44         case SEMCTL: {
  45                 unsigned long arg;
  46                 if (!ptr)
  47                         return -EINVAL;
  48                 if (get_user(arg, (unsigned long __user *) ptr))
  49                         return -EFAULT;
  50                 return ksys_old_semctl(first, second, third, arg);
  51         }
  52 
  53         case MSGSND:
  54                 return ksys_msgsnd(first, (struct msgbuf __user *) ptr,
  55                                   second, third);
  56         case MSGRCV:
  57                 switch (version) {
  58                 case 0: {
  59                         struct ipc_kludge tmp;
  60                         if (!ptr)
  61                                 return -EINVAL;
  62 
  63                         if (copy_from_user(&tmp,
  64                                            (struct ipc_kludge __user *) ptr,
  65                                            sizeof(tmp)))
  66                                 return -EFAULT;
  67                         return ksys_msgrcv(first, tmp.msgp, second,
  68                                            tmp.msgtyp, third);
  69                 }
  70                 default:
  71                         return ksys_msgrcv(first,
  72                                            (struct msgbuf __user *) ptr,
  73                                            second, fifth, third);
  74                 }
  75         case MSGGET:
  76                 return ksys_msgget((key_t) first, second);
  77         case MSGCTL:
  78                 return ksys_old_msgctl(first, second,
  79                                    (struct msqid_ds __user *)ptr);
  80 
  81         case SHMAT:
  82                 switch (version) {
  83                 default: {
  84                         unsigned long raddr;
  85                         ret = do_shmat(first, (char __user *)ptr,
  86                                        second, &raddr, SHMLBA);
  87                         if (ret)
  88                                 return ret;
  89                         return put_user(raddr, (unsigned long __user *) third);
  90                 }
  91                 case 1:
  92                         /*
  93                          * This was the entry point for kernel-originating calls
  94                          * from iBCS2 in 2.2 days.
  95                          */
  96                         return -EINVAL;
  97                 }
  98         case SHMDT:
  99                 return ksys_shmdt((char __user *)ptr);
 100         case SHMGET:
 101                 return ksys_shmget(first, second, third);
 102         case SHMCTL:
 103                 return ksys_old_shmctl(first, second,
 104                                    (struct shmid_ds __user *) ptr);
 105         default:
 106                 return -ENOSYS;
 107         }
 108 }
 109 
 110 SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second,
 111                 unsigned long, third, void __user *, ptr, long, fifth)
 112 {
 113         return ksys_ipc(call, first, second, third, ptr, fifth);
 114 }
 115 #endif
 116 
 117 #ifdef CONFIG_COMPAT
 118 #include <linux/compat.h>
 119 
 120 #ifndef COMPAT_SHMLBA
 121 #define COMPAT_SHMLBA   SHMLBA
 122 #endif
 123 
 124 struct compat_ipc_kludge {
 125         compat_uptr_t msgp;
 126         compat_long_t msgtyp;
 127 };
 128 
 129 #ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC
 130 int compat_ksys_ipc(u32 call, int first, int second,
 131         u32 third, compat_uptr_t ptr, u32 fifth)
 132 {
 133         int version;
 134         u32 pad;
 135 
 136         version = call >> 16; /* hack for backward compatibility */
 137         call &= 0xffff;
 138 
 139         switch (call) {
 140         case SEMOP:
 141                 /* struct sembuf is the same on 32 and 64bit :)) */
 142                 return ksys_semtimedop(first, compat_ptr(ptr), second, NULL);
 143         case SEMTIMEDOP:
 144                 if (!IS_ENABLED(CONFIG_COMPAT_32BIT_TIME))
 145                         return -ENOSYS;
 146                 return compat_ksys_semtimedop(first, compat_ptr(ptr), second,
 147                                                 compat_ptr(fifth));
 148         case SEMGET:
 149                 return ksys_semget(first, second, third);
 150         case SEMCTL:
 151                 if (!ptr)
 152                         return -EINVAL;
 153                 if (get_user(pad, (u32 __user *) compat_ptr(ptr)))
 154                         return -EFAULT;
 155                 return compat_ksys_old_semctl(first, second, third, pad);
 156 
 157         case MSGSND:
 158                 return compat_ksys_msgsnd(first, ptr, second, third);
 159 
 160         case MSGRCV: {
 161                 void __user *uptr = compat_ptr(ptr);
 162 
 163                 if (first < 0 || second < 0)
 164                         return -EINVAL;
 165 
 166                 if (!version) {
 167                         struct compat_ipc_kludge ipck;
 168                         if (!uptr)
 169                                 return -EINVAL;
 170                         if (copy_from_user(&ipck, uptr, sizeof(ipck)))
 171                                 return -EFAULT;
 172                         return compat_ksys_msgrcv(first, ipck.msgp, second,
 173                                                  ipck.msgtyp, third);
 174                 }
 175                 return compat_ksys_msgrcv(first, ptr, second, fifth, third);
 176         }
 177         case MSGGET:
 178                 return ksys_msgget(first, second);
 179         case MSGCTL:
 180                 return compat_ksys_old_msgctl(first, second, compat_ptr(ptr));
 181 
 182         case SHMAT: {
 183                 int err;
 184                 unsigned long raddr;
 185 
 186                 if (version == 1)
 187                         return -EINVAL;
 188                 err = do_shmat(first, compat_ptr(ptr), second, &raddr,
 189                                COMPAT_SHMLBA);
 190                 if (err < 0)
 191                         return err;
 192                 return put_user(raddr, (compat_ulong_t __user *)compat_ptr(third));
 193         }
 194         case SHMDT:
 195                 return ksys_shmdt(compat_ptr(ptr));
 196         case SHMGET:
 197                 return ksys_shmget(first, (unsigned int)second, third);
 198         case SHMCTL:
 199                 return compat_ksys_old_shmctl(first, second, compat_ptr(ptr));
 200         }
 201 
 202         return -ENOSYS;
 203 }
 204 
 205 COMPAT_SYSCALL_DEFINE6(ipc, u32, call, int, first, int, second,
 206         u32, third, compat_uptr_t, ptr, u32, fifth)
 207 {
 208         return compat_ksys_ipc(call, first, second, third, ptr, fifth);
 209 }
 210 #endif
 211 #endif

/* [<][>][^][v][top][bottom][index][help] */