aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/ia64/Kconfig.debug5
-rw-r--r--fs/utimes.c23
-rw-r--r--include/linux/audit.h6
-rw-r--r--include/linux/compat.h9
-rw-r--r--include/linux/msg.h15
-rw-r--r--include/linux/sem.h3
-rw-r--r--include/linux/shm.h6
-rw-r--r--include/linux/time.h2
-rw-r--r--init/initramfs.c2
-rw-r--r--ipc/compat.c740
-rw-r--r--ipc/mqueue.c28
-rw-r--r--ipc/msg.c366
-rw-r--r--ipc/sem.c344
-rw-r--r--ipc/shm.c533
-rw-r--r--ipc/syscall.c90
-rw-r--r--ipc/util.h30
-rw-r--r--kernel/audit.h2
-rw-r--r--kernel/auditsc.c12
-rw-r--r--kernel/compat.c23
19 files changed, 1044 insertions, 1195 deletions
diff --git a/arch/ia64/Kconfig.debug b/arch/ia64/Kconfig.debug
index de9d507ba0fd..4763887ba368 100644
--- a/arch/ia64/Kconfig.debug
+++ b/arch/ia64/Kconfig.debug
@@ -56,9 +56,4 @@ config IA64_DEBUG_IRQ
56 and restore instructions. It's useful for tracking down spinlock 56 and restore instructions. It's useful for tracking down spinlock
57 problems, but slow! If you're unsure, select N. 57 problems, but slow! If you're unsure, select N.
58 58
59config SYSVIPC_COMPAT
60 bool
61 depends on COMPAT && SYSVIPC
62 default y
63
64endmenu 59endmenu
diff --git a/fs/utimes.c b/fs/utimes.c
index 6571d8c848a0..51edb9f9507c 100644
--- a/fs/utimes.c
+++ b/fs/utimes.c
@@ -22,7 +22,7 @@
22 */ 22 */
23SYSCALL_DEFINE2(utime, char __user *, filename, struct utimbuf __user *, times) 23SYSCALL_DEFINE2(utime, char __user *, filename, struct utimbuf __user *, times)
24{ 24{
25 struct timespec tv[2]; 25 struct timespec64 tv[2];
26 26
27 if (times) { 27 if (times) {
28 if (get_user(tv[0].tv_sec, &times->actime) || 28 if (get_user(tv[0].tv_sec, &times->actime) ||
@@ -44,7 +44,7 @@ static bool nsec_valid(long nsec)
44 return nsec >= 0 && nsec <= 999999999; 44 return nsec >= 0 && nsec <= 999999999;
45} 45}
46 46
47static int utimes_common(const struct path *path, struct timespec *times) 47static int utimes_common(const struct path *path, struct timespec64 *times)
48{ 48{
49 int error; 49 int error;
50 struct iattr newattrs; 50 struct iattr newattrs;
@@ -115,7 +115,7 @@ out:
115 * must be owner or have write permission. 115 * must be owner or have write permission.
116 * Else, update from *times, must be owner or super user. 116 * Else, update from *times, must be owner or super user.
117 */ 117 */
118long do_utimes(int dfd, const char __user *filename, struct timespec *times, 118long do_utimes(int dfd, const char __user *filename, struct timespec64 *times,
119 int flags) 119 int flags)
120{ 120{
121 int error = -EINVAL; 121 int error = -EINVAL;
@@ -167,10 +167,11 @@ out:
167SYSCALL_DEFINE4(utimensat, int, dfd, const char __user *, filename, 167SYSCALL_DEFINE4(utimensat, int, dfd, const char __user *, filename,
168 struct timespec __user *, utimes, int, flags) 168 struct timespec __user *, utimes, int, flags)
169{ 169{
170 struct timespec tstimes[2]; 170 struct timespec64 tstimes[2];
171 171
172 if (utimes) { 172 if (utimes) {
173 if (copy_from_user(&tstimes, utimes, sizeof(tstimes))) 173 if ((get_timespec64(&tstimes[0], &utimes[0]) ||
174 get_timespec64(&tstimes[1], &utimes[1])))
174 return -EFAULT; 175 return -EFAULT;
175 176
176 /* Nothing to do, we must not even check the path. */ 177 /* Nothing to do, we must not even check the path. */
@@ -186,7 +187,7 @@ SYSCALL_DEFINE3(futimesat, int, dfd, const char __user *, filename,
186 struct timeval __user *, utimes) 187 struct timeval __user *, utimes)
187{ 188{
188 struct timeval times[2]; 189 struct timeval times[2];
189 struct timespec tstimes[2]; 190 struct timespec64 tstimes[2];
190 191
191 if (utimes) { 192 if (utimes) {
192 if (copy_from_user(&times, utimes, sizeof(times))) 193 if (copy_from_user(&times, utimes, sizeof(times)))
@@ -224,7 +225,7 @@ SYSCALL_DEFINE2(utimes, char __user *, filename,
224COMPAT_SYSCALL_DEFINE2(utime, const char __user *, filename, 225COMPAT_SYSCALL_DEFINE2(utime, const char __user *, filename,
225 struct compat_utimbuf __user *, t) 226 struct compat_utimbuf __user *, t)
226{ 227{
227 struct timespec tv[2]; 228 struct timespec64 tv[2];
228 229
229 if (t) { 230 if (t) {
230 if (get_user(tv[0].tv_sec, &t->actime) || 231 if (get_user(tv[0].tv_sec, &t->actime) ||
@@ -238,11 +239,11 @@ COMPAT_SYSCALL_DEFINE2(utime, const char __user *, filename,
238 239
239COMPAT_SYSCALL_DEFINE4(utimensat, unsigned int, dfd, const char __user *, filename, struct compat_timespec __user *, t, int, flags) 240COMPAT_SYSCALL_DEFINE4(utimensat, unsigned int, dfd, const char __user *, filename, struct compat_timespec __user *, t, int, flags)
240{ 241{
241 struct timespec tv[2]; 242 struct timespec64 tv[2];
242 243
243 if (t) { 244 if (t) {
244 if (compat_get_timespec(&tv[0], &t[0]) || 245 if (compat_get_timespec64(&tv[0], &t[0]) ||
245 compat_get_timespec(&tv[1], &t[1])) 246 compat_get_timespec64(&tv[1], &t[1]))
246 return -EFAULT; 247 return -EFAULT;
247 248
248 if (tv[0].tv_nsec == UTIME_OMIT && tv[1].tv_nsec == UTIME_OMIT) 249 if (tv[0].tv_nsec == UTIME_OMIT && tv[1].tv_nsec == UTIME_OMIT)
@@ -253,7 +254,7 @@ COMPAT_SYSCALL_DEFINE4(utimensat, unsigned int, dfd, const char __user *, filena
253 254
254COMPAT_SYSCALL_DEFINE3(futimesat, unsigned int, dfd, const char __user *, filename, struct compat_timeval __user *, t) 255COMPAT_SYSCALL_DEFINE3(futimesat, unsigned int, dfd, const char __user *, filename, struct compat_timeval __user *, t)
255{ 256{
256 struct timespec tv[2]; 257 struct timespec64 tv[2];
257 258
258 if (t) { 259 if (t) {
259 if (get_user(tv[0].tv_sec, &t[0].tv_sec) || 260 if (get_user(tv[0].tv_sec, &t[0].tv_sec) ||
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 2150bdccfbab..74d4d4e8e3db 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -351,7 +351,7 @@ extern int __audit_socketcall(int nargs, unsigned long *args);
351extern int __audit_sockaddr(int len, void *addr); 351extern int __audit_sockaddr(int len, void *addr);
352extern void __audit_fd_pair(int fd1, int fd2); 352extern void __audit_fd_pair(int fd1, int fd2);
353extern void __audit_mq_open(int oflag, umode_t mode, struct mq_attr *attr); 353extern void __audit_mq_open(int oflag, umode_t mode, struct mq_attr *attr);
354extern void __audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec *abs_timeout); 354extern void __audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec64 *abs_timeout);
355extern void __audit_mq_notify(mqd_t mqdes, const struct sigevent *notification); 355extern void __audit_mq_notify(mqd_t mqdes, const struct sigevent *notification);
356extern void __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat); 356extern void __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat);
357extern int __audit_log_bprm_fcaps(struct linux_binprm *bprm, 357extern int __audit_log_bprm_fcaps(struct linux_binprm *bprm,
@@ -412,7 +412,7 @@ static inline void audit_mq_open(int oflag, umode_t mode, struct mq_attr *attr)
412 if (unlikely(!audit_dummy_context())) 412 if (unlikely(!audit_dummy_context()))
413 __audit_mq_open(oflag, mode, attr); 413 __audit_mq_open(oflag, mode, attr);
414} 414}
415static inline void audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec *abs_timeout) 415static inline void audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec64 *abs_timeout)
416{ 416{
417 if (unlikely(!audit_dummy_context())) 417 if (unlikely(!audit_dummy_context()))
418 __audit_mq_sendrecv(mqdes, msg_len, msg_prio, abs_timeout); 418 __audit_mq_sendrecv(mqdes, msg_len, msg_prio, abs_timeout);
@@ -549,7 +549,7 @@ static inline void audit_mq_open(int oflag, umode_t mode, struct mq_attr *attr)
549{ } 549{ }
550static inline void audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, 550static inline void audit_mq_sendrecv(mqd_t mqdes, size_t msg_len,
551 unsigned int msg_prio, 551 unsigned int msg_prio,
552 const struct timespec *abs_timeout) 552 const struct timespec64 *abs_timeout)
553{ } 553{ }
554static inline void audit_mq_notify(mqd_t mqdes, 554static inline void audit_mq_notify(mqd_t mqdes,
555 const struct sigevent *notification) 555 const struct sigevent *notification)
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 3fc433303d7a..a5619de3437d 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -171,15 +171,6 @@ extern int get_compat_itimerspec64(struct itimerspec64 *its,
171extern int put_compat_itimerspec64(const struct itimerspec64 *its, 171extern int put_compat_itimerspec64(const struct itimerspec64 *its,
172 struct compat_itimerspec __user *uits); 172 struct compat_itimerspec __user *uits);
173 173
174/*
175 * This function convert a timespec if necessary and returns a *user
176 * space* pointer. If no conversion is necessary, it returns the
177 * initial pointer. NULL is a legitimate argument and will always
178 * output NULL.
179 */
180extern int compat_convert_timespec(struct timespec __user **,
181 const void __user *);
182
183struct compat_iovec { 174struct compat_iovec {
184 compat_uptr_t iov_base; 175 compat_uptr_t iov_base;
185 compat_size_t iov_len; 176 compat_size_t iov_len;
diff --git a/include/linux/msg.h b/include/linux/msg.h
index a001305f5a79..81263fe3f9dc 100644
--- a/include/linux/msg.h
+++ b/include/linux/msg.h
@@ -2,6 +2,7 @@
2#define _LINUX_MSG_H 2#define _LINUX_MSG_H
3 3
4#include <linux/list.h> 4#include <linux/list.h>
5#include <linux/time64.h>
5#include <uapi/linux/msg.h> 6#include <uapi/linux/msg.h>
6 7
7/* one msg_msg structure for each message */ 8/* one msg_msg structure for each message */
@@ -17,9 +18,9 @@ struct msg_msg {
17/* one msq_queue structure for each present queue on the system */ 18/* one msq_queue structure for each present queue on the system */
18struct msg_queue { 19struct msg_queue {
19 struct kern_ipc_perm q_perm; 20 struct kern_ipc_perm q_perm;
20 time_t q_stime; /* last msgsnd time */ 21 time64_t q_stime; /* last msgsnd time */
21 time_t q_rtime; /* last msgrcv time */ 22 time64_t q_rtime; /* last msgrcv time */
22 time_t q_ctime; /* last change time */ 23 time64_t q_ctime; /* last change time */
23 unsigned long q_cbytes; /* current number of bytes on queue */ 24 unsigned long q_cbytes; /* current number of bytes on queue */
24 unsigned long q_qnum; /* number of messages in queue */ 25 unsigned long q_qnum; /* number of messages in queue */
25 unsigned long q_qbytes; /* max number of bytes on queue */ 26 unsigned long q_qbytes; /* max number of bytes on queue */
@@ -31,12 +32,4 @@ struct msg_queue {
31 struct list_head q_senders; 32 struct list_head q_senders;
32} __randomize_layout; 33} __randomize_layout;
33 34
34/* Helper routines for sys_msgsnd and sys_msgrcv */
35extern long do_msgsnd(int msqid, long mtype, void __user *mtext,
36 size_t msgsz, int msgflg);
37extern long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
38 int msgflg,
39 long (*msg_fill)(void __user *, struct msg_msg *,
40 size_t));
41
42#endif /* _LINUX_MSG_H */ 35#endif /* _LINUX_MSG_H */
diff --git a/include/linux/sem.h b/include/linux/sem.h
index de2deb8676bd..0083128318f6 100644
--- a/include/linux/sem.h
+++ b/include/linux/sem.h
@@ -4,6 +4,7 @@
4#include <linux/atomic.h> 4#include <linux/atomic.h>
5#include <linux/rcupdate.h> 5#include <linux/rcupdate.h>
6#include <linux/cache.h> 6#include <linux/cache.h>
7#include <linux/time64.h>
7#include <uapi/linux/sem.h> 8#include <uapi/linux/sem.h>
8 9
9struct task_struct; 10struct task_struct;
@@ -30,7 +31,7 @@ struct sem {
30/* One sem_array data structure for each set of semaphores in the system. */ 31/* One sem_array data structure for each set of semaphores in the system. */
31struct sem_array { 32struct sem_array {
32 struct kern_ipc_perm sem_perm; /* permissions .. see ipc.h */ 33 struct kern_ipc_perm sem_perm; /* permissions .. see ipc.h */
33 time_t sem_ctime; /* create/last semctl() time */ 34 time64_t sem_ctime; /* create/last semctl() time */
34 struct list_head pending_alter; /* pending operations */ 35 struct list_head pending_alter; /* pending operations */
35 /* that alter the array */ 36 /* that alter the array */
36 struct list_head pending_const; /* pending complex operations */ 37 struct list_head pending_const; /* pending complex operations */
diff --git a/include/linux/shm.h b/include/linux/shm.h
index 21a5e6c43385..74a4b3b64352 100644
--- a/include/linux/shm.h
+++ b/include/linux/shm.h
@@ -12,9 +12,9 @@ struct shmid_kernel /* private to the kernel */
12 struct file *shm_file; 12 struct file *shm_file;
13 unsigned long shm_nattch; 13 unsigned long shm_nattch;
14 unsigned long shm_segsz; 14 unsigned long shm_segsz;
15 time_t shm_atim; 15 time64_t shm_atim;
16 time_t shm_dtim; 16 time64_t shm_dtim;
17 time_t shm_ctim; 17 time64_t shm_ctim;
18 pid_t shm_cprid; 18 pid_t shm_cprid;
19 pid_t shm_lprid; 19 pid_t shm_lprid;
20 struct user_struct *mlock_user; 20 struct user_struct *mlock_user;
diff --git a/include/linux/time.h b/include/linux/time.h
index 3877136bbdf8..9bc1f945777c 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -178,7 +178,7 @@ extern int do_setitimer(int which, struct itimerval *value,
178 struct itimerval *ovalue); 178 struct itimerval *ovalue);
179extern int do_getitimer(int which, struct itimerval *value); 179extern int do_getitimer(int which, struct itimerval *value);
180 180
181extern long do_utimes(int dfd, const char __user *filename, struct timespec *times, int flags); 181extern long do_utimes(int dfd, const char __user *filename, struct timespec64 *times, int flags);
182 182
183/* 183/*
184 * Similar to the struct tm in userspace <time.h>, but it needs to be here so 184 * Similar to the struct tm in userspace <time.h>, but it needs to be here so
diff --git a/init/initramfs.c b/init/initramfs.c
index 8a532050043f..e64bf7b4c1ca 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -110,7 +110,7 @@ static void __init free_hash(void)
110 110
111static long __init do_utime(char *filename, time_t mtime) 111static long __init do_utime(char *filename, time_t mtime)
112{ 112{
113 struct timespec t[2]; 113 struct timespec64 t[2];
114 114
115 t[0].tv_sec = mtime; 115 t[0].tv_sec = mtime;
116 t[0].tv_nsec = 0; 116 t[0].tv_nsec = 0;
diff --git a/ipc/compat.c b/ipc/compat.c
index 9b3c85f8a538..b17bf93d7b49 100644
--- a/ipc/compat.c
+++ b/ipc/compat.c
@@ -34,724 +34,48 @@
34 34
35#include "util.h" 35#include "util.h"
36 36
37struct compat_msgbuf { 37int get_compat_ipc64_perm(struct ipc64_perm *to,
38 compat_long_t mtype; 38 struct compat_ipc64_perm __user *from)
39 char mtext[1];
40};
41
42struct compat_ipc_perm {
43 key_t key;
44 __compat_uid_t uid;
45 __compat_gid_t gid;
46 __compat_uid_t cuid;
47 __compat_gid_t cgid;
48 compat_mode_t mode;
49 unsigned short seq;
50};
51
52struct compat_semid_ds {
53 struct compat_ipc_perm sem_perm;
54 compat_time_t sem_otime;
55 compat_time_t sem_ctime;
56 compat_uptr_t sem_base;
57 compat_uptr_t sem_pending;
58 compat_uptr_t sem_pending_last;
59 compat_uptr_t undo;
60 unsigned short sem_nsems;
61};
62
63struct compat_msqid_ds {
64 struct compat_ipc_perm msg_perm;
65 compat_uptr_t msg_first;
66 compat_uptr_t msg_last;
67 compat_time_t msg_stime;
68 compat_time_t msg_rtime;
69 compat_time_t msg_ctime;
70 compat_ulong_t msg_lcbytes;
71 compat_ulong_t msg_lqbytes;
72 unsigned short msg_cbytes;
73 unsigned short msg_qnum;
74 unsigned short msg_qbytes;
75 compat_ipc_pid_t msg_lspid;
76 compat_ipc_pid_t msg_lrpid;
77};
78
79struct compat_shmid_ds {
80 struct compat_ipc_perm shm_perm;
81 int shm_segsz;
82 compat_time_t shm_atime;
83 compat_time_t shm_dtime;
84 compat_time_t shm_ctime;
85 compat_ipc_pid_t shm_cpid;
86 compat_ipc_pid_t shm_lpid;
87 unsigned short shm_nattch;
88 unsigned short shm_unused;
89 compat_uptr_t shm_unused2;
90 compat_uptr_t shm_unused3;
91};
92
93struct compat_ipc_kludge {
94 compat_uptr_t msgp;
95 compat_long_t msgtyp;
96};
97
98struct compat_shminfo64 {
99 compat_ulong_t shmmax;
100 compat_ulong_t shmmin;
101 compat_ulong_t shmmni;
102 compat_ulong_t shmseg;
103 compat_ulong_t shmall;
104 compat_ulong_t __unused1;
105 compat_ulong_t __unused2;
106 compat_ulong_t __unused3;
107 compat_ulong_t __unused4;
108};
109
110struct compat_shm_info {
111 compat_int_t used_ids;
112 compat_ulong_t shm_tot, shm_rss, shm_swp;
113 compat_ulong_t swap_attempts, swap_successes;
114};
115
116static inline int compat_ipc_parse_version(int *cmd)
117{
118#ifdef CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION
119 int version = *cmd & IPC_64;
120
121 /* this is tricky: architectures that have support for the old
122 * ipc structures in 64 bit binaries need to have IPC_64 set
123 * in cmd, the others need to have it cleared */
124#ifndef ipc_parse_version
125 *cmd |= IPC_64;
126#else
127 *cmd &= ~IPC_64;
128#endif
129 return version;
130#else
131 /* With the asm-generic APIs, we always use the 64-bit versions. */
132 return IPC_64;
133#endif
134}
135
136static inline int __get_compat_ipc64_perm(struct ipc64_perm *p64,
137 struct compat_ipc64_perm __user *up64)
138{
139 int err;
140
141 err = __get_user(p64->uid, &up64->uid);
142 err |= __get_user(p64->gid, &up64->gid);
143 err |= __get_user(p64->mode, &up64->mode);
144 return err;
145}
146
147static inline int __get_compat_ipc_perm(struct ipc64_perm *p,
148 struct compat_ipc_perm __user *up)
149{
150 int err;
151
152 err = __get_user(p->uid, &up->uid);
153 err |= __get_user(p->gid, &up->gid);
154 err |= __get_user(p->mode, &up->mode);
155 return err;
156}
157
158static inline int __put_compat_ipc64_perm(struct ipc64_perm *p64,
159 struct compat_ipc64_perm __user *up64)
160{ 39{
161 int err; 40 struct compat_ipc64_perm v;
162 41 if (copy_from_user(&v, from, sizeof(v)))
163 err = __put_user(p64->key, &up64->key);
164 err |= __put_user(p64->uid, &up64->uid);
165 err |= __put_user(p64->gid, &up64->gid);
166 err |= __put_user(p64->cuid, &up64->cuid);
167 err |= __put_user(p64->cgid, &up64->cgid);
168 err |= __put_user(p64->mode, &up64->mode);
169 err |= __put_user(p64->seq, &up64->seq);
170 return err;
171}
172
173static inline int __put_compat_ipc_perm(struct ipc64_perm *p,
174 struct compat_ipc_perm __user *uip)
175{
176 int err;
177 __compat_uid_t u;
178 __compat_gid_t g;
179
180 err = __put_user(p->key, &uip->key);
181 SET_UID(u, p->uid);
182 err |= __put_user(u, &uip->uid);
183 SET_GID(g, p->gid);
184 err |= __put_user(g, &uip->gid);
185 SET_UID(u, p->cuid);
186 err |= __put_user(u, &uip->cuid);
187 SET_GID(g, p->cgid);
188 err |= __put_user(g, &uip->cgid);
189 err |= __put_user(p->mode, &uip->mode);
190 err |= __put_user(p->seq, &uip->seq);
191 return err;
192}
193
194static inline int get_compat_semid64_ds(struct semid64_ds *sem64,
195 struct compat_semid64_ds __user *up64)
196{
197 if (!access_ok(VERIFY_READ, up64, sizeof(*up64)))
198 return -EFAULT;
199 return __get_compat_ipc64_perm(&sem64->sem_perm, &up64->sem_perm);
200}
201
202static inline int get_compat_semid_ds(struct semid64_ds *s,
203 struct compat_semid_ds __user *up)
204{
205 if (!access_ok(VERIFY_READ, up, sizeof(*up)))
206 return -EFAULT; 42 return -EFAULT;
207 return __get_compat_ipc_perm(&s->sem_perm, &up->sem_perm); 43 to->uid = v.uid;
44 to->gid = v.gid;
45 to->mode = v.mode;
46 return 0;
208} 47}
209 48
210static inline int put_compat_semid64_ds(struct semid64_ds *sem64, 49int get_compat_ipc_perm(struct ipc64_perm *to,
211 struct compat_semid64_ds __user *up64) 50 struct compat_ipc_perm __user *from)
212{ 51{
213 int err; 52 struct compat_ipc_perm v;
214 53 if (copy_from_user(&v, from, sizeof(v)))
215 if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64)))
216 return -EFAULT; 54 return -EFAULT;
217 err = __put_compat_ipc64_perm(&sem64->sem_perm, &up64->sem_perm); 55 to->uid = v.uid;
218 err |= __put_user(sem64->sem_otime, &up64->sem_otime); 56 to->gid = v.gid;
219 err |= __put_user(sem64->sem_ctime, &up64->sem_ctime); 57 to->mode = v.mode;
220 err |= __put_user(sem64->sem_nsems, &up64->sem_nsems); 58 return 0;
221 return err;
222} 59}
223 60
224static inline int put_compat_semid_ds(struct semid64_ds *s, 61void to_compat_ipc64_perm(struct compat_ipc64_perm *to, struct ipc64_perm *from)
225 struct compat_semid_ds __user *up)
226{ 62{
227 int err; 63 to->key = from->key;
228 64 to->uid = from->uid;
229 if (!access_ok(VERIFY_WRITE, up, sizeof(*up))) 65 to->gid = from->gid;
230 return -EFAULT; 66 to->cuid = from->cuid;
231 err = __put_compat_ipc_perm(&s->sem_perm, &up->sem_perm); 67 to->cgid = from->cgid;
232 err |= __put_user(s->sem_otime, &up->sem_otime); 68 to->mode = from->mode;
233 err |= __put_user(s->sem_ctime, &up->sem_ctime); 69 to->seq = from->seq;
234 err |= __put_user(s->sem_nsems, &up->sem_nsems);
235 return err;
236} 70}
237 71
238static long do_compat_semctl(int first, int second, int third, u32 pad) 72void to_compat_ipc_perm(struct compat_ipc_perm *to, struct ipc64_perm *from)
239{ 73{
240 unsigned long fourth; 74 to->key = from->key;
241 int err, err2; 75 SET_UID(to->uid, from->uid);
242 struct semid64_ds sem64; 76 SET_GID(to->gid, from->gid);
243 struct semid64_ds __user *up64; 77 SET_UID(to->cuid, from->cuid);
244 int version = compat_ipc_parse_version(&third); 78 SET_GID(to->cgid, from->cgid);
245 79 to->mode = from->mode;
246 memset(&sem64, 0, sizeof(sem64)); 80 to->seq = from->seq;
247
248 if ((third & (~IPC_64)) == SETVAL)
249#ifdef __BIG_ENDIAN
250 fourth = (unsigned long)pad << 32;
251#else
252 fourth = pad;
253#endif
254 else
255 fourth = (unsigned long)compat_ptr(pad);
256 switch (third & (~IPC_64)) {
257 case IPC_INFO:
258 case IPC_RMID:
259 case SEM_INFO:
260 case GETVAL:
261 case GETPID:
262 case GETNCNT:
263 case GETZCNT:
264 case GETALL:
265 case SETVAL:
266 case SETALL:
267 err = sys_semctl(first, second, third, fourth);
268 break;
269
270 case IPC_STAT:
271 case SEM_STAT:
272 up64 = compat_alloc_user_space(sizeof(sem64));
273 fourth = (unsigned long)up64;
274 err = sys_semctl(first, second, third, fourth);
275 if (err < 0)
276 break;
277 if (copy_from_user(&sem64, up64, sizeof(sem64)))
278 err2 = -EFAULT;
279 else if (version == IPC_64)
280 err2 = put_compat_semid64_ds(&sem64, compat_ptr(pad));
281 else
282 err2 = put_compat_semid_ds(&sem64, compat_ptr(pad));
283 if (err2)
284 err = -EFAULT;
285 break;
286
287 case IPC_SET:
288 if (version == IPC_64)
289 err = get_compat_semid64_ds(&sem64, compat_ptr(pad));
290 else
291 err = get_compat_semid_ds(&sem64, compat_ptr(pad));
292
293 up64 = compat_alloc_user_space(sizeof(sem64));
294 if (copy_to_user(up64, &sem64, sizeof(sem64)))
295 err = -EFAULT;
296 if (err)
297 break;
298
299 fourth = (unsigned long)up64;
300 err = sys_semctl(first, second, third, fourth);
301 break;
302
303 default:
304 err = -EINVAL;
305 break;
306 }
307 return err;
308}
309
310static long compat_do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz)
311{
312 struct compat_msgbuf __user *msgp = dest;
313 size_t msgsz;
314
315 if (put_user(msg->m_type, &msgp->mtype))
316 return -EFAULT;
317
318 msgsz = (bufsz > msg->m_ts) ? msg->m_ts : bufsz;
319 if (store_msg(msgp->mtext, msg, msgsz))
320 return -EFAULT;
321 return msgsz;
322}
323
324#ifndef COMPAT_SHMLBA
325#define COMPAT_SHMLBA SHMLBA
326#endif
327
328#ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC
329COMPAT_SYSCALL_DEFINE6(ipc, u32, call, int, first, int, second,
330 u32, third, compat_uptr_t, ptr, u32, fifth)
331{
332 int version;
333 u32 pad;
334
335 version = call >> 16; /* hack for backward compatibility */
336 call &= 0xffff;
337
338 switch (call) {
339 case SEMOP:
340 /* struct sembuf is the same on 32 and 64bit :)) */
341 return sys_semtimedop(first, compat_ptr(ptr), second, NULL);
342 case SEMTIMEDOP:
343 return compat_sys_semtimedop(first, compat_ptr(ptr), second,
344 compat_ptr(fifth));
345 case SEMGET:
346 return sys_semget(first, second, third);
347 case SEMCTL:
348 if (!ptr)
349 return -EINVAL;
350 if (get_user(pad, (u32 __user *) compat_ptr(ptr)))
351 return -EFAULT;
352 return do_compat_semctl(first, second, third, pad);
353
354 case MSGSND: {
355 struct compat_msgbuf __user *up = compat_ptr(ptr);
356 compat_long_t type;
357
358 if (first < 0 || second < 0)
359 return -EINVAL;
360
361 if (get_user(type, &up->mtype))
362 return -EFAULT;
363
364 return do_msgsnd(first, type, up->mtext, second, third);
365 }
366 case MSGRCV: {
367 void __user *uptr = compat_ptr(ptr);
368
369 if (first < 0 || second < 0)
370 return -EINVAL;
371
372 if (!version) {
373 struct compat_ipc_kludge ipck;
374 if (!uptr)
375 return -EINVAL;
376 if (copy_from_user(&ipck, uptr, sizeof(ipck)))
377 return -EFAULT;
378 uptr = compat_ptr(ipck.msgp);
379 fifth = ipck.msgtyp;
380 }
381 return do_msgrcv(first, uptr, second, (s32)fifth, third,
382 compat_do_msg_fill);
383 }
384 case MSGGET:
385 return sys_msgget(first, second);
386 case MSGCTL:
387 return compat_sys_msgctl(first, second, compat_ptr(ptr));
388
389 case SHMAT: {
390 int err;
391 unsigned long raddr;
392
393 if (version == 1)
394 return -EINVAL;
395 err = do_shmat(first, compat_ptr(ptr), second, &raddr,
396 COMPAT_SHMLBA);
397 if (err < 0)
398 return err;
399 return put_user(raddr, (compat_ulong_t *)compat_ptr(third));
400 }
401 case SHMDT:
402 return sys_shmdt(compat_ptr(ptr));
403 case SHMGET:
404 return sys_shmget(first, (unsigned)second, third);
405 case SHMCTL:
406 return compat_sys_shmctl(first, second, compat_ptr(ptr));
407 }
408
409 return -ENOSYS;
410}
411#endif
412
413COMPAT_SYSCALL_DEFINE4(semctl, int, semid, int, semnum, int, cmd, int, arg)
414{
415 return do_compat_semctl(semid, semnum, cmd, arg);
416}
417
418COMPAT_SYSCALL_DEFINE4(msgsnd, int, msqid, compat_uptr_t, msgp,
419 compat_ssize_t, msgsz, int, msgflg)
420{
421 struct compat_msgbuf __user *up = compat_ptr(msgp);
422 compat_long_t mtype;
423
424 if (get_user(mtype, &up->mtype))
425 return -EFAULT;
426 return do_msgsnd(msqid, mtype, up->mtext, (ssize_t)msgsz, msgflg);
427}
428
429COMPAT_SYSCALL_DEFINE5(msgrcv, int, msqid, compat_uptr_t, msgp,
430 compat_ssize_t, msgsz, compat_long_t, msgtyp, int, msgflg)
431{
432 return do_msgrcv(msqid, compat_ptr(msgp), (ssize_t)msgsz, (long)msgtyp,
433 msgflg, compat_do_msg_fill);
434}
435
436static inline int get_compat_msqid64(struct msqid64_ds *m64,
437 struct compat_msqid64_ds __user *up64)
438{
439 int err;
440
441 if (!access_ok(VERIFY_READ, up64, sizeof(*up64)))
442 return -EFAULT;
443 err = __get_compat_ipc64_perm(&m64->msg_perm, &up64->msg_perm);
444 err |= __get_user(m64->msg_qbytes, &up64->msg_qbytes);
445 return err;
446}
447
448static inline int get_compat_msqid(struct msqid64_ds *m,
449 struct compat_msqid_ds __user *up)
450{
451 int err;
452
453 if (!access_ok(VERIFY_READ, up, sizeof(*up)))
454 return -EFAULT;
455 err = __get_compat_ipc_perm(&m->msg_perm, &up->msg_perm);
456 err |= __get_user(m->msg_qbytes, &up->msg_qbytes);
457 return err;
458}
459
460static inline int put_compat_msqid64_ds(struct msqid64_ds *m64,
461 struct compat_msqid64_ds __user *up64)
462{
463 int err;
464
465 if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64)))
466 return -EFAULT;
467 err = __put_compat_ipc64_perm(&m64->msg_perm, &up64->msg_perm);
468 err |= __put_user(m64->msg_stime, &up64->msg_stime);
469 err |= __put_user(m64->msg_rtime, &up64->msg_rtime);
470 err |= __put_user(m64->msg_ctime, &up64->msg_ctime);
471 err |= __put_user(m64->msg_cbytes, &up64->msg_cbytes);
472 err |= __put_user(m64->msg_qnum, &up64->msg_qnum);
473 err |= __put_user(m64->msg_qbytes, &up64->msg_qbytes);
474 err |= __put_user(m64->msg_lspid, &up64->msg_lspid);
475 err |= __put_user(m64->msg_lrpid, &up64->msg_lrpid);
476 return err;
477}
478
479static inline int put_compat_msqid_ds(struct msqid64_ds *m,
480 struct compat_msqid_ds __user *up)
481{
482 int err;
483
484 if (!access_ok(VERIFY_WRITE, up, sizeof(*up)))
485 return -EFAULT;
486 err = __put_compat_ipc_perm(&m->msg_perm, &up->msg_perm);
487 err |= __put_user(m->msg_stime, &up->msg_stime);
488 err |= __put_user(m->msg_rtime, &up->msg_rtime);
489 err |= __put_user(m->msg_ctime, &up->msg_ctime);
490 err |= __put_user(m->msg_cbytes, &up->msg_cbytes);
491 err |= __put_user(m->msg_qnum, &up->msg_qnum);
492 err |= __put_user(m->msg_qbytes, &up->msg_qbytes);
493 err |= __put_user(m->msg_lspid, &up->msg_lspid);
494 err |= __put_user(m->msg_lrpid, &up->msg_lrpid);
495 return err;
496}
497
498COMPAT_SYSCALL_DEFINE3(msgctl, int, first, int, second, void __user *, uptr)
499{
500 int err, err2;
501 struct msqid64_ds m64;
502 int version = compat_ipc_parse_version(&second);
503 void __user *p;
504
505 memset(&m64, 0, sizeof(m64));
506
507 switch (second & (~IPC_64)) {
508 case IPC_INFO:
509 case IPC_RMID:
510 case MSG_INFO:
511 err = sys_msgctl(first, second, uptr);
512 break;
513
514 case IPC_SET:
515 if (version == IPC_64)
516 err = get_compat_msqid64(&m64, uptr);
517 else
518 err = get_compat_msqid(&m64, uptr);
519
520 if (err)
521 break;
522 p = compat_alloc_user_space(sizeof(m64));
523 if (copy_to_user(p, &m64, sizeof(m64)))
524 err = -EFAULT;
525 else
526 err = sys_msgctl(first, second, p);
527 break;
528
529 case IPC_STAT:
530 case MSG_STAT:
531 p = compat_alloc_user_space(sizeof(m64));
532 err = sys_msgctl(first, second, p);
533 if (err < 0)
534 break;
535 if (copy_from_user(&m64, p, sizeof(m64)))
536 err2 = -EFAULT;
537 else if (version == IPC_64)
538 err2 = put_compat_msqid64_ds(&m64, uptr);
539 else
540 err2 = put_compat_msqid_ds(&m64, uptr);
541 if (err2)
542 err = -EFAULT;
543 break;
544
545 default:
546 err = -EINVAL;
547 break;
548 }
549 return err;
550}
551
552COMPAT_SYSCALL_DEFINE3(shmat, int, shmid, compat_uptr_t, shmaddr, int, shmflg)
553{
554 unsigned long ret;
555 long err;
556
557 err = do_shmat(shmid, compat_ptr(shmaddr), shmflg, &ret, COMPAT_SHMLBA);
558 if (err)
559 return err;
560 force_successful_syscall_return();
561 return (long)ret;
562}
563
564static inline int get_compat_shmid64_ds(struct shmid64_ds *sem64,
565 struct compat_shmid64_ds __user *up64)
566{
567 if (!access_ok(VERIFY_READ, up64, sizeof(*up64)))
568 return -EFAULT;
569 return __get_compat_ipc64_perm(&sem64->shm_perm, &up64->shm_perm);
570}
571
572static inline int get_compat_shmid_ds(struct shmid64_ds *s,
573 struct compat_shmid_ds __user *up)
574{
575 if (!access_ok(VERIFY_READ, up, sizeof(*up)))
576 return -EFAULT;
577 return __get_compat_ipc_perm(&s->shm_perm, &up->shm_perm);
578}
579
580static inline int put_compat_shmid64_ds(struct shmid64_ds *sem64,
581 struct compat_shmid64_ds __user *up64)
582{
583 int err;
584
585 if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64)))
586 return -EFAULT;
587 err = __put_compat_ipc64_perm(&sem64->shm_perm, &up64->shm_perm);
588 err |= __put_user(sem64->shm_atime, &up64->shm_atime);
589 err |= __put_user(sem64->shm_dtime, &up64->shm_dtime);
590 err |= __put_user(sem64->shm_ctime, &up64->shm_ctime);
591 err |= __put_user(sem64->shm_segsz, &up64->shm_segsz);
592 err |= __put_user(sem64->shm_nattch, &up64->shm_nattch);
593 err |= __put_user(sem64->shm_cpid, &up64->shm_cpid);
594 err |= __put_user(sem64->shm_lpid, &up64->shm_lpid);
595 return err;
596}
597
598static inline int put_compat_shmid_ds(struct shmid64_ds *s,
599 struct compat_shmid_ds __user *up)
600{
601 int err;
602
603 if (!access_ok(VERIFY_WRITE, up, sizeof(*up)))
604 return -EFAULT;
605 err = __put_compat_ipc_perm(&s->shm_perm, &up->shm_perm);
606 err |= __put_user(s->shm_atime, &up->shm_atime);
607 err |= __put_user(s->shm_dtime, &up->shm_dtime);
608 err |= __put_user(s->shm_ctime, &up->shm_ctime);
609 err |= __put_user(s->shm_segsz, &up->shm_segsz);
610 err |= __put_user(s->shm_nattch, &up->shm_nattch);
611 err |= __put_user(s->shm_cpid, &up->shm_cpid);
612 err |= __put_user(s->shm_lpid, &up->shm_lpid);
613 return err;
614}
615
616static inline int put_compat_shminfo64(struct shminfo64 *smi,
617 struct compat_shminfo64 __user *up64)
618{
619 int err;
620
621 if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64)))
622 return -EFAULT;
623 if (smi->shmmax > INT_MAX)
624 smi->shmmax = INT_MAX;
625 err = __put_user(smi->shmmax, &up64->shmmax);
626 err |= __put_user(smi->shmmin, &up64->shmmin);
627 err |= __put_user(smi->shmmni, &up64->shmmni);
628 err |= __put_user(smi->shmseg, &up64->shmseg);
629 err |= __put_user(smi->shmall, &up64->shmall);
630 return err;
631}
632
633static inline int put_compat_shminfo(struct shminfo64 *smi,
634 struct shminfo __user *up)
635{
636 int err;
637
638 if (!access_ok(VERIFY_WRITE, up, sizeof(*up)))
639 return -EFAULT;
640 if (smi->shmmax > INT_MAX)
641 smi->shmmax = INT_MAX;
642 err = __put_user(smi->shmmax, &up->shmmax);
643 err |= __put_user(smi->shmmin, &up->shmmin);
644 err |= __put_user(smi->shmmni, &up->shmmni);
645 err |= __put_user(smi->shmseg, &up->shmseg);
646 err |= __put_user(smi->shmall, &up->shmall);
647 return err;
648}
649
650static inline int put_compat_shm_info(struct shm_info __user *ip,
651 struct compat_shm_info __user *uip)
652{
653 int err;
654 struct shm_info si;
655
656 if (!access_ok(VERIFY_WRITE, uip, sizeof(*uip)) ||
657 copy_from_user(&si, ip, sizeof(si)))
658 return -EFAULT;
659 err = __put_user(si.used_ids, &uip->used_ids);
660 err |= __put_user(si.shm_tot, &uip->shm_tot);
661 err |= __put_user(si.shm_rss, &uip->shm_rss);
662 err |= __put_user(si.shm_swp, &uip->shm_swp);
663 err |= __put_user(si.swap_attempts, &uip->swap_attempts);
664 err |= __put_user(si.swap_successes, &uip->swap_successes);
665 return err;
666}
667
668COMPAT_SYSCALL_DEFINE3(shmctl, int, first, int, second, void __user *, uptr)
669{
670 void __user *p;
671 struct shmid64_ds sem64;
672 struct shminfo64 smi;
673 int err, err2;
674 int version = compat_ipc_parse_version(&second);
675
676 memset(&sem64, 0, sizeof(sem64));
677
678 switch (second & (~IPC_64)) {
679 case IPC_RMID:
680 case SHM_LOCK:
681 case SHM_UNLOCK:
682 err = sys_shmctl(first, second, uptr);
683 break;
684
685 case IPC_INFO:
686 p = compat_alloc_user_space(sizeof(smi));
687 err = sys_shmctl(first, second, p);
688 if (err < 0)
689 break;
690 if (copy_from_user(&smi, p, sizeof(smi)))
691 err2 = -EFAULT;
692 else if (version == IPC_64)
693 err2 = put_compat_shminfo64(&smi, uptr);
694 else
695 err2 = put_compat_shminfo(&smi, uptr);
696 if (err2)
697 err = -EFAULT;
698 break;
699
700
701 case IPC_SET:
702 if (version == IPC_64)
703 err = get_compat_shmid64_ds(&sem64, uptr);
704 else
705 err = get_compat_shmid_ds(&sem64, uptr);
706
707 if (err)
708 break;
709 p = compat_alloc_user_space(sizeof(sem64));
710 if (copy_to_user(p, &sem64, sizeof(sem64)))
711 err = -EFAULT;
712 else
713 err = sys_shmctl(first, second, p);
714 break;
715
716 case IPC_STAT:
717 case SHM_STAT:
718 p = compat_alloc_user_space(sizeof(sem64));
719 err = sys_shmctl(first, second, p);
720 if (err < 0)
721 break;
722 if (copy_from_user(&sem64, p, sizeof(sem64)))
723 err2 = -EFAULT;
724 else if (version == IPC_64)
725 err2 = put_compat_shmid64_ds(&sem64, uptr);
726 else
727 err2 = put_compat_shmid_ds(&sem64, uptr);
728 if (err2)
729 err = -EFAULT;
730 break;
731
732 case SHM_INFO:
733 p = compat_alloc_user_space(sizeof(struct shm_info));
734 err = sys_shmctl(first, second, p);
735 if (err < 0)
736 break;
737 err2 = put_compat_shm_info(p, uptr);
738 if (err2)
739 err = -EFAULT;
740 break;
741
742 default:
743 err = -EINVAL;
744 break;
745 }
746 return err;
747}
748
749COMPAT_SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsems,
750 unsigned, nsops,
751 const struct compat_timespec __user *, timeout)
752{
753 struct timespec __user *ts64;
754 if (compat_convert_timespec(&ts64, timeout))
755 return -EFAULT;
756 return sys_semtimedop(semid, tsems, nsops, ts64);
757} 81}
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index eb1391b52c6f..d24025626310 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -668,11 +668,11 @@ static void __do_notify(struct mqueue_inode_info *info)
668} 668}
669 669
670static int prepare_timeout(const struct timespec __user *u_abs_timeout, 670static int prepare_timeout(const struct timespec __user *u_abs_timeout,
671 struct timespec *ts) 671 struct timespec64 *ts)
672{ 672{
673 if (copy_from_user(ts, u_abs_timeout, sizeof(struct timespec))) 673 if (get_timespec64(ts, u_abs_timeout))
674 return -EFAULT; 674 return -EFAULT;
675 if (!timespec_valid(ts)) 675 if (!timespec64_valid(ts))
676 return -EINVAL; 676 return -EINVAL;
677 return 0; 677 return 0;
678} 678}
@@ -962,7 +962,7 @@ static inline void pipelined_receive(struct wake_q_head *wake_q,
962 962
963static int do_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr, 963static int do_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr,
964 size_t msg_len, unsigned int msg_prio, 964 size_t msg_len, unsigned int msg_prio,
965 struct timespec *ts) 965 struct timespec64 *ts)
966{ 966{
967 struct fd f; 967 struct fd f;
968 struct inode *inode; 968 struct inode *inode;
@@ -979,7 +979,7 @@ static int do_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr,
979 return -EINVAL; 979 return -EINVAL;
980 980
981 if (ts) { 981 if (ts) {
982 expires = timespec_to_ktime(*ts); 982 expires = timespec64_to_ktime(*ts);
983 timeout = &expires; 983 timeout = &expires;
984 } 984 }
985 985
@@ -1080,7 +1080,7 @@ out:
1080 1080
1081static int do_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr, 1081static int do_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr,
1082 size_t msg_len, unsigned int __user *u_msg_prio, 1082 size_t msg_len, unsigned int __user *u_msg_prio,
1083 struct timespec *ts) 1083 struct timespec64 *ts)
1084{ 1084{
1085 ssize_t ret; 1085 ssize_t ret;
1086 struct msg_msg *msg_ptr; 1086 struct msg_msg *msg_ptr;
@@ -1092,7 +1092,7 @@ static int do_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr,
1092 struct posix_msg_tree_node *new_leaf = NULL; 1092 struct posix_msg_tree_node *new_leaf = NULL;
1093 1093
1094 if (ts) { 1094 if (ts) {
1095 expires = timespec_to_ktime(*ts); 1095 expires = timespec64_to_ktime(*ts);
1096 timeout = &expires; 1096 timeout = &expires;
1097 } 1097 }
1098 1098
@@ -1184,7 +1184,7 @@ SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr,
1184 size_t, msg_len, unsigned int, msg_prio, 1184 size_t, msg_len, unsigned int, msg_prio,
1185 const struct timespec __user *, u_abs_timeout) 1185 const struct timespec __user *, u_abs_timeout)
1186{ 1186{
1187 struct timespec ts, *p = NULL; 1187 struct timespec64 ts, *p = NULL;
1188 if (u_abs_timeout) { 1188 if (u_abs_timeout) {
1189 int res = prepare_timeout(u_abs_timeout, &ts); 1189 int res = prepare_timeout(u_abs_timeout, &ts);
1190 if (res) 1190 if (res)
@@ -1198,7 +1198,7 @@ SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr,
1198 size_t, msg_len, unsigned int __user *, u_msg_prio, 1198 size_t, msg_len, unsigned int __user *, u_msg_prio,
1199 const struct timespec __user *, u_abs_timeout) 1199 const struct timespec __user *, u_abs_timeout)
1200{ 1200{
1201 struct timespec ts, *p = NULL; 1201 struct timespec64 ts, *p = NULL;
1202 if (u_abs_timeout) { 1202 if (u_abs_timeout) {
1203 int res = prepare_timeout(u_abs_timeout, &ts); 1203 int res = prepare_timeout(u_abs_timeout, &ts);
1204 if (res) 1204 if (res)
@@ -1475,11 +1475,11 @@ COMPAT_SYSCALL_DEFINE4(mq_open, const char __user *, u_name,
1475} 1475}
1476 1476
1477static int compat_prepare_timeout(const struct compat_timespec __user *p, 1477static int compat_prepare_timeout(const struct compat_timespec __user *p,
1478 struct timespec *ts) 1478 struct timespec64 *ts)
1479{ 1479{
1480 if (compat_get_timespec(ts, p)) 1480 if (compat_get_timespec64(ts, p))
1481 return -EFAULT; 1481 return -EFAULT;
1482 if (!timespec_valid(ts)) 1482 if (!timespec64_valid(ts))
1483 return -EINVAL; 1483 return -EINVAL;
1484 return 0; 1484 return 0;
1485} 1485}
@@ -1489,7 +1489,7 @@ COMPAT_SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes,
1489 compat_size_t, msg_len, unsigned int, msg_prio, 1489 compat_size_t, msg_len, unsigned int, msg_prio,
1490 const struct compat_timespec __user *, u_abs_timeout) 1490 const struct compat_timespec __user *, u_abs_timeout)
1491{ 1491{
1492 struct timespec ts, *p = NULL; 1492 struct timespec64 ts, *p = NULL;
1493 if (u_abs_timeout) { 1493 if (u_abs_timeout) {
1494 int res = compat_prepare_timeout(u_abs_timeout, &ts); 1494 int res = compat_prepare_timeout(u_abs_timeout, &ts);
1495 if (res) 1495 if (res)
@@ -1504,7 +1504,7 @@ COMPAT_SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes,
1504 compat_size_t, msg_len, unsigned int __user *, u_msg_prio, 1504 compat_size_t, msg_len, unsigned int __user *, u_msg_prio,
1505 const struct compat_timespec __user *, u_abs_timeout) 1505 const struct compat_timespec __user *, u_abs_timeout)
1506{ 1506{
1507 struct timespec ts, *p = NULL; 1507 struct timespec64 ts, *p = NULL;
1508 if (u_abs_timeout) { 1508 if (u_abs_timeout) {
1509 int res = compat_prepare_timeout(u_abs_timeout, &ts); 1509 int res = compat_prepare_timeout(u_abs_timeout, &ts);
1510 if (res) 1510 if (res)
diff --git a/ipc/msg.c b/ipc/msg.c
index df82bc9a5531..06be5a9adfa4 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -133,7 +133,7 @@ static int newque(struct ipc_namespace *ns, struct ipc_params *params)
133 } 133 }
134 134
135 msq->q_stime = msq->q_rtime = 0; 135 msq->q_stime = msq->q_rtime = 0;
136 msq->q_ctime = get_seconds(); 136 msq->q_ctime = ktime_get_real_seconds();
137 msq->q_cbytes = msq->q_qnum = 0; 137 msq->q_cbytes = msq->q_qnum = 0;
138 msq->q_qbytes = ns->msg_ctlmnb; 138 msq->q_qbytes = ns->msg_ctlmnb;
139 msq->q_lspid = msq->q_lrpid = 0; 139 msq->q_lspid = msq->q_lrpid = 0;
@@ -361,23 +361,17 @@ copy_msqid_from_user(struct msqid64_ds *out, void __user *buf, int version)
361 * NOTE: no locks must be held, the rwsem is taken inside this function. 361 * NOTE: no locks must be held, the rwsem is taken inside this function.
362 */ 362 */
363static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd, 363static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,
364 struct msqid_ds __user *buf, int version) 364 struct msqid64_ds *msqid64)
365{ 365{
366 struct kern_ipc_perm *ipcp; 366 struct kern_ipc_perm *ipcp;
367 struct msqid64_ds uninitialized_var(msqid64);
368 struct msg_queue *msq; 367 struct msg_queue *msq;
369 int err; 368 int err;
370 369
371 if (cmd == IPC_SET) {
372 if (copy_msqid_from_user(&msqid64, buf, version))
373 return -EFAULT;
374 }
375
376 down_write(&msg_ids(ns).rwsem); 370 down_write(&msg_ids(ns).rwsem);
377 rcu_read_lock(); 371 rcu_read_lock();
378 372
379 ipcp = ipcctl_pre_down_nolock(ns, &msg_ids(ns), msqid, cmd, 373 ipcp = ipcctl_pre_down_nolock(ns, &msg_ids(ns), msqid, cmd,
380 &msqid64.msg_perm, msqid64.msg_qbytes); 374 &msqid64->msg_perm, msqid64->msg_qbytes);
381 if (IS_ERR(ipcp)) { 375 if (IS_ERR(ipcp)) {
382 err = PTR_ERR(ipcp); 376 err = PTR_ERR(ipcp);
383 goto out_unlock1; 377 goto out_unlock1;
@@ -399,20 +393,20 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,
399 { 393 {
400 DEFINE_WAKE_Q(wake_q); 394 DEFINE_WAKE_Q(wake_q);
401 395
402 if (msqid64.msg_qbytes > ns->msg_ctlmnb && 396 if (msqid64->msg_qbytes > ns->msg_ctlmnb &&
403 !capable(CAP_SYS_RESOURCE)) { 397 !capable(CAP_SYS_RESOURCE)) {
404 err = -EPERM; 398 err = -EPERM;
405 goto out_unlock1; 399 goto out_unlock1;
406 } 400 }
407 401
408 ipc_lock_object(&msq->q_perm); 402 ipc_lock_object(&msq->q_perm);
409 err = ipc_update_perm(&msqid64.msg_perm, ipcp); 403 err = ipc_update_perm(&msqid64->msg_perm, ipcp);
410 if (err) 404 if (err)
411 goto out_unlock0; 405 goto out_unlock0;
412 406
413 msq->q_qbytes = msqid64.msg_qbytes; 407 msq->q_qbytes = msqid64->msg_qbytes;
414 408
415 msq->q_ctime = get_seconds(); 409 msq->q_ctime = ktime_get_real_seconds();
416 /* 410 /*
417 * Sleeping receivers might be excluded by 411 * Sleeping receivers might be excluded by
418 * stricter permissions. 412 * stricter permissions.
@@ -442,111 +436,89 @@ out_up:
442 return err; 436 return err;
443} 437}
444 438
445static int msgctl_nolock(struct ipc_namespace *ns, int msqid, 439static int msgctl_info(struct ipc_namespace *ns, int msqid,
446 int cmd, int version, void __user *buf) 440 int cmd, struct msginfo *msginfo)
447{ 441{
448 int err; 442 int err;
449 struct msg_queue *msq; 443 int max_id;
450
451 switch (cmd) {
452 case IPC_INFO:
453 case MSG_INFO:
454 {
455 struct msginfo msginfo;
456 int max_id;
457
458 if (!buf)
459 return -EFAULT;
460
461 /*
462 * We must not return kernel stack data.
463 * due to padding, it's not enough
464 * to set all member fields.
465 */
466 err = security_msg_queue_msgctl(NULL, cmd);
467 if (err)
468 return err;
469 444
470 memset(&msginfo, 0, sizeof(msginfo)); 445 /*
471 msginfo.msgmni = ns->msg_ctlmni; 446 * We must not return kernel stack data.
472 msginfo.msgmax = ns->msg_ctlmax; 447 * due to padding, it's not enough
473 msginfo.msgmnb = ns->msg_ctlmnb; 448 * to set all member fields.
474 msginfo.msgssz = MSGSSZ; 449 */
475 msginfo.msgseg = MSGSEG; 450 err = security_msg_queue_msgctl(NULL, cmd);
476 down_read(&msg_ids(ns).rwsem); 451 if (err)
477 if (cmd == MSG_INFO) { 452 return err;
478 msginfo.msgpool = msg_ids(ns).in_use; 453
479 msginfo.msgmap = atomic_read(&ns->msg_hdrs); 454 memset(msginfo, 0, sizeof(*msginfo));
480 msginfo.msgtql = atomic_read(&ns->msg_bytes); 455 msginfo->msgmni = ns->msg_ctlmni;
481 } else { 456 msginfo->msgmax = ns->msg_ctlmax;
482 msginfo.msgmap = MSGMAP; 457 msginfo->msgmnb = ns->msg_ctlmnb;
483 msginfo.msgpool = MSGPOOL; 458 msginfo->msgssz = MSGSSZ;
484 msginfo.msgtql = MSGTQL; 459 msginfo->msgseg = MSGSEG;
485 } 460 down_read(&msg_ids(ns).rwsem);
486 max_id = ipc_get_maxid(&msg_ids(ns)); 461 if (cmd == MSG_INFO) {
487 up_read(&msg_ids(ns).rwsem); 462 msginfo->msgpool = msg_ids(ns).in_use;
488 if (copy_to_user(buf, &msginfo, sizeof(struct msginfo))) 463 msginfo->msgmap = atomic_read(&ns->msg_hdrs);
489 return -EFAULT; 464 msginfo->msgtql = atomic_read(&ns->msg_bytes);
490 return (max_id < 0) ? 0 : max_id; 465 } else {
466 msginfo->msgmap = MSGMAP;
467 msginfo->msgpool = MSGPOOL;
468 msginfo->msgtql = MSGTQL;
491 } 469 }
470 max_id = ipc_get_maxid(&msg_ids(ns));
471 up_read(&msg_ids(ns).rwsem);
472 return (max_id < 0) ? 0 : max_id;
473}
492 474
493 case MSG_STAT: 475static int msgctl_stat(struct ipc_namespace *ns, int msqid,
494 case IPC_STAT: 476 int cmd, struct msqid64_ds *p)
495 { 477{
496 struct msqid64_ds tbuf; 478 int err;
497 int success_return; 479 struct msg_queue *msq;
498 480 int success_return;
499 if (!buf)
500 return -EFAULT;
501
502 memset(&tbuf, 0, sizeof(tbuf));
503 481
504 rcu_read_lock(); 482 memset(p, 0, sizeof(*p));
505 if (cmd == MSG_STAT) {
506 msq = msq_obtain_object(ns, msqid);
507 if (IS_ERR(msq)) {
508 err = PTR_ERR(msq);
509 goto out_unlock;
510 }
511 success_return = msq->q_perm.id;
512 } else {
513 msq = msq_obtain_object_check(ns, msqid);
514 if (IS_ERR(msq)) {
515 err = PTR_ERR(msq);
516 goto out_unlock;
517 }
518 success_return = 0;
519 }
520 483
521 err = -EACCES; 484 rcu_read_lock();
522 if (ipcperms(ns, &msq->q_perm, S_IRUGO)) 485 if (cmd == MSG_STAT) {
486 msq = msq_obtain_object(ns, msqid);
487 if (IS_ERR(msq)) {
488 err = PTR_ERR(msq);
523 goto out_unlock; 489 goto out_unlock;
524 490 }
525 err = security_msg_queue_msgctl(msq, cmd); 491 success_return = msq->q_perm.id;
526 if (err) 492 } else {
493 msq = msq_obtain_object_check(ns, msqid);
494 if (IS_ERR(msq)) {
495 err = PTR_ERR(msq);
527 goto out_unlock; 496 goto out_unlock;
497 }
498 success_return = 0;
499 }
528 500
529 kernel_to_ipc64_perm(&msq->q_perm, &tbuf.msg_perm); 501 err = -EACCES;
530 tbuf.msg_stime = msq->q_stime; 502 if (ipcperms(ns, &msq->q_perm, S_IRUGO))
531 tbuf.msg_rtime = msq->q_rtime; 503 goto out_unlock;
532 tbuf.msg_ctime = msq->q_ctime;
533 tbuf.msg_cbytes = msq->q_cbytes;
534 tbuf.msg_qnum = msq->q_qnum;
535 tbuf.msg_qbytes = msq->q_qbytes;
536 tbuf.msg_lspid = msq->q_lspid;
537 tbuf.msg_lrpid = msq->q_lrpid;
538 rcu_read_unlock();
539 504
540 if (copy_msqid_to_user(buf, &tbuf, version)) 505 err = security_msg_queue_msgctl(msq, cmd);
541 return -EFAULT; 506 if (err)
542 return success_return; 507 goto out_unlock;
543 } 508
509 kernel_to_ipc64_perm(&msq->q_perm, &p->msg_perm);
510 p->msg_stime = msq->q_stime;
511 p->msg_rtime = msq->q_rtime;
512 p->msg_ctime = msq->q_ctime;
513 p->msg_cbytes = msq->q_cbytes;
514 p->msg_qnum = msq->q_qnum;
515 p->msg_qbytes = msq->q_qbytes;
516 p->msg_lspid = msq->q_lspid;
517 p->msg_lrpid = msq->q_lrpid;
518 rcu_read_unlock();
544 519
545 default: 520 return success_return;
546 return -EINVAL;
547 }
548 521
549 return err;
550out_unlock: 522out_unlock:
551 rcu_read_unlock(); 523 rcu_read_unlock();
552 return err; 524 return err;
@@ -556,6 +528,8 @@ SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf)
556{ 528{
557 int version; 529 int version;
558 struct ipc_namespace *ns; 530 struct ipc_namespace *ns;
531 struct msqid64_ds msqid64;
532 int err;
559 533
560 if (msqid < 0 || cmd < 0) 534 if (msqid < 0 || cmd < 0)
561 return -EINVAL; 535 return -EINVAL;
@@ -565,18 +539,147 @@ SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf)
565 539
566 switch (cmd) { 540 switch (cmd) {
567 case IPC_INFO: 541 case IPC_INFO:
568 case MSG_INFO: 542 case MSG_INFO: {
543 struct msginfo msginfo;
544 err = msgctl_info(ns, msqid, cmd, &msginfo);
545 if (err < 0)
546 return err;
547 if (copy_to_user(buf, &msginfo, sizeof(struct msginfo)))
548 err = -EFAULT;
549 return err;
550 }
569 case MSG_STAT: /* msqid is an index rather than a msg queue id */ 551 case MSG_STAT: /* msqid is an index rather than a msg queue id */
570 case IPC_STAT: 552 case IPC_STAT:
571 return msgctl_nolock(ns, msqid, cmd, version, buf); 553 err = msgctl_stat(ns, msqid, cmd, &msqid64);
554 if (err < 0)
555 return err;
556 if (copy_msqid_to_user(buf, &msqid64, version))
557 err = -EFAULT;
558 return err;
572 case IPC_SET: 559 case IPC_SET:
560 if (copy_msqid_from_user(&msqid64, buf, version))
561 return -EFAULT;
562 /* fallthru */
573 case IPC_RMID: 563 case IPC_RMID:
574 return msgctl_down(ns, msqid, cmd, buf, version); 564 return msgctl_down(ns, msqid, cmd, &msqid64);
575 default: 565 default:
576 return -EINVAL; 566 return -EINVAL;
577 } 567 }
578} 568}
579 569
570#ifdef CONFIG_COMPAT
571
572struct compat_msqid_ds {
573 struct compat_ipc_perm msg_perm;
574 compat_uptr_t msg_first;
575 compat_uptr_t msg_last;
576 compat_time_t msg_stime;
577 compat_time_t msg_rtime;
578 compat_time_t msg_ctime;
579 compat_ulong_t msg_lcbytes;
580 compat_ulong_t msg_lqbytes;
581 unsigned short msg_cbytes;
582 unsigned short msg_qnum;
583 unsigned short msg_qbytes;
584 compat_ipc_pid_t msg_lspid;
585 compat_ipc_pid_t msg_lrpid;
586};
587
588static int copy_compat_msqid_from_user(struct msqid64_ds *out, void __user *buf,
589 int version)
590{
591 memset(out, 0, sizeof(*out));
592 if (version == IPC_64) {
593 struct compat_msqid64_ds *p = buf;
594 if (get_compat_ipc64_perm(&out->msg_perm, &p->msg_perm))
595 return -EFAULT;
596 if (get_user(out->msg_qbytes, &p->msg_qbytes))
597 return -EFAULT;
598 } else {
599 struct compat_msqid_ds *p = buf;
600 if (get_compat_ipc_perm(&out->msg_perm, &p->msg_perm))
601 return -EFAULT;
602 if (get_user(out->msg_qbytes, &p->msg_qbytes))
603 return -EFAULT;
604 }
605 return 0;
606}
607
608static int copy_compat_msqid_to_user(void __user *buf, struct msqid64_ds *in,
609 int version)
610{
611 if (version == IPC_64) {
612 struct compat_msqid64_ds v;
613 memset(&v, 0, sizeof(v));
614 to_compat_ipc64_perm(&v.msg_perm, &in->msg_perm);
615 v.msg_stime = in->msg_stime;
616 v.msg_rtime = in->msg_rtime;
617 v.msg_ctime = in->msg_ctime;
618 v.msg_cbytes = in->msg_cbytes;
619 v.msg_qnum = in->msg_qnum;
620 v.msg_qbytes = in->msg_qbytes;
621 v.msg_lspid = in->msg_lspid;
622 v.msg_lrpid = in->msg_lrpid;
623 return copy_to_user(buf, &v, sizeof(v));
624 } else {
625 struct compat_msqid_ds v;
626 memset(&v, 0, sizeof(v));
627 to_compat_ipc_perm(&v.msg_perm, &in->msg_perm);
628 v.msg_stime = in->msg_stime;
629 v.msg_rtime = in->msg_rtime;
630 v.msg_ctime = in->msg_ctime;
631 v.msg_cbytes = in->msg_cbytes;
632 v.msg_qnum = in->msg_qnum;
633 v.msg_qbytes = in->msg_qbytes;
634 v.msg_lspid = in->msg_lspid;
635 v.msg_lrpid = in->msg_lrpid;
636 return copy_to_user(buf, &v, sizeof(v));
637 }
638}
639
640COMPAT_SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, void __user *, uptr)
641{
642 struct ipc_namespace *ns;
643 int err;
644 struct msqid64_ds msqid64;
645 int version = compat_ipc_parse_version(&cmd);
646
647 ns = current->nsproxy->ipc_ns;
648
649 if (msqid < 0 || cmd < 0)
650 return -EINVAL;
651
652 switch (cmd & (~IPC_64)) {
653 case IPC_INFO:
654 case MSG_INFO: {
655 struct msginfo msginfo;
656 err = msgctl_info(ns, msqid, cmd, &msginfo);
657 if (err < 0)
658 return err;
659 if (copy_to_user(uptr, &msginfo, sizeof(struct msginfo)))
660 err = -EFAULT;
661 return err;
662 }
663 case IPC_STAT:
664 case MSG_STAT:
665 err = msgctl_stat(ns, msqid, cmd, &msqid64);
666 if (err < 0)
667 return err;
668 if (copy_compat_msqid_to_user(uptr, &msqid64, version))
669 err = -EFAULT;
670 return err;
671 case IPC_SET:
672 if (copy_compat_msqid_from_user(&msqid64, uptr, version))
673 return -EFAULT;
674 /* fallthru */
675 case IPC_RMID:
676 return msgctl_down(ns, msqid, cmd, &msqid64);
677 default:
678 return -EINVAL;
679 }
680}
681#endif
682
580static int testmsg(struct msg_msg *msg, long type, int mode) 683static int testmsg(struct msg_msg *msg, long type, int mode)
581{ 684{
582 switch (mode) { 685 switch (mode) {
@@ -627,7 +730,7 @@ static inline int pipelined_send(struct msg_queue *msq, struct msg_msg *msg,
627 return 0; 730 return 0;
628} 731}
629 732
630long do_msgsnd(int msqid, long mtype, void __user *mtext, 733static long do_msgsnd(int msqid, long mtype, void __user *mtext,
631 size_t msgsz, int msgflg) 734 size_t msgsz, int msgflg)
632{ 735{
633 struct msg_queue *msq; 736 struct msg_queue *msq;
@@ -750,6 +853,25 @@ SYSCALL_DEFINE4(msgsnd, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz,
750 return do_msgsnd(msqid, mtype, msgp->mtext, msgsz, msgflg); 853 return do_msgsnd(msqid, mtype, msgp->mtext, msgsz, msgflg);
751} 854}
752 855
856#ifdef CONFIG_COMPAT
857
858struct compat_msgbuf {
859 compat_long_t mtype;
860 char mtext[1];
861};
862
863COMPAT_SYSCALL_DEFINE4(msgsnd, int, msqid, compat_uptr_t, msgp,
864 compat_ssize_t, msgsz, int, msgflg)
865{
866 struct compat_msgbuf __user *up = compat_ptr(msgp);
867 compat_long_t mtype;
868
869 if (get_user(mtype, &up->mtype))
870 return -EFAULT;
871 return do_msgsnd(msqid, mtype, up->mtext, (ssize_t)msgsz, msgflg);
872}
873#endif
874
753static inline int convert_mode(long *msgtyp, int msgflg) 875static inline int convert_mode(long *msgtyp, int msgflg)
754{ 876{
755 if (msgflg & MSG_COPY) 877 if (msgflg & MSG_COPY)
@@ -846,7 +968,7 @@ static struct msg_msg *find_msg(struct msg_queue *msq, long *msgtyp, int mode)
846 return found ?: ERR_PTR(-EAGAIN); 968 return found ?: ERR_PTR(-EAGAIN);
847} 969}
848 970
849long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, int msgflg, 971static long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, int msgflg,
850 long (*msg_handler)(void __user *, struct msg_msg *, size_t)) 972 long (*msg_handler)(void __user *, struct msg_msg *, size_t))
851{ 973{
852 int mode; 974 int mode;
@@ -1010,6 +1132,28 @@ SYSCALL_DEFINE5(msgrcv, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz,
1010 return do_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg, do_msg_fill); 1132 return do_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg, do_msg_fill);
1011} 1133}
1012 1134
1135#ifdef CONFIG_COMPAT
1136static long compat_do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz)
1137{
1138 struct compat_msgbuf __user *msgp = dest;
1139 size_t msgsz;
1140
1141 if (put_user(msg->m_type, &msgp->mtype))
1142 return -EFAULT;
1143
1144 msgsz = (bufsz > msg->m_ts) ? msg->m_ts : bufsz;
1145 if (store_msg(msgp->mtext, msg, msgsz))
1146 return -EFAULT;
1147 return msgsz;
1148}
1149
1150COMPAT_SYSCALL_DEFINE5(msgrcv, int, msqid, compat_uptr_t, msgp,
1151 compat_ssize_t, msgsz, compat_long_t, msgtyp, int, msgflg)
1152{
1153 return do_msgrcv(msqid, compat_ptr(msgp), (ssize_t)msgsz, (long)msgtyp,
1154 msgflg, compat_do_msg_fill);
1155}
1156#endif
1013 1157
1014int msg_init_ns(struct ipc_namespace *ns) 1158int msg_init_ns(struct ipc_namespace *ns)
1015{ 1159{
@@ -1039,7 +1183,7 @@ static int sysvipc_msg_proc_show(struct seq_file *s, void *it)
1039 struct msg_queue *msq = container_of(ipcp, struct msg_queue, q_perm); 1183 struct msg_queue *msq = container_of(ipcp, struct msg_queue, q_perm);
1040 1184
1041 seq_printf(s, 1185 seq_printf(s,
1042 "%10d %10d %4o %10lu %10lu %5u %5u %5u %5u %5u %5u %10lu %10lu %10lu\n", 1186 "%10d %10d %4o %10lu %10lu %5u %5u %5u %5u %5u %5u %10llu %10llu %10llu\n",
1043 msq->q_perm.key, 1187 msq->q_perm.key,
1044 msq->q_perm.id, 1188 msq->q_perm.id,
1045 msq->q_perm.mode, 1189 msq->q_perm.mode,
diff --git a/ipc/sem.c b/ipc/sem.c
index 013c7981f3c7..f7385bce5fd3 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -512,7 +512,7 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params)
512 INIT_LIST_HEAD(&sma->pending_const); 512 INIT_LIST_HEAD(&sma->pending_const);
513 INIT_LIST_HEAD(&sma->list_id); 513 INIT_LIST_HEAD(&sma->list_id);
514 sma->sem_nsems = nsems; 514 sma->sem_nsems = nsems;
515 sma->sem_ctime = get_seconds(); 515 sma->sem_ctime = ktime_get_real_seconds();
516 516
517 retval = ipc_addid(&sem_ids(ns), &sma->sem_perm, ns->sc_semmni); 517 retval = ipc_addid(&sem_ids(ns), &sma->sem_perm, ns->sc_semmni);
518 if (retval < 0) { 518 if (retval < 0) {
@@ -1163,14 +1163,14 @@ static unsigned long copy_semid_to_user(void __user *buf, struct semid64_ds *in,
1163 } 1163 }
1164} 1164}
1165 1165
1166static time_t get_semotime(struct sem_array *sma) 1166static time64_t get_semotime(struct sem_array *sma)
1167{ 1167{
1168 int i; 1168 int i;
1169 time_t res; 1169 time64_t res;
1170 1170
1171 res = sma->sems[0].sem_otime; 1171 res = sma->sems[0].sem_otime;
1172 for (i = 1; i < sma->sem_nsems; i++) { 1172 for (i = 1; i < sma->sem_nsems; i++) {
1173 time_t to = sma->sems[i].sem_otime; 1173 time64_t to = sma->sems[i].sem_otime;
1174 1174
1175 if (to > res) 1175 if (to > res)
1176 res = to; 1176 res = to;
@@ -1178,112 +1178,95 @@ static time_t get_semotime(struct sem_array *sma)
1178 return res; 1178 return res;
1179} 1179}
1180 1180
1181static int semctl_nolock(struct ipc_namespace *ns, int semid, 1181static int semctl_stat(struct ipc_namespace *ns, int semid,
1182 int cmd, int version, void __user *p) 1182 int cmd, struct semid64_ds *semid64)
1183{ 1183{
1184 int err;
1185 struct sem_array *sma; 1184 struct sem_array *sma;
1185 int id = 0;
1186 int err;
1186 1187
1187 switch (cmd) { 1188 memset(semid64, 0, sizeof(*semid64));
1188 case IPC_INFO:
1189 case SEM_INFO:
1190 {
1191 struct seminfo seminfo;
1192 int max_id;
1193
1194 err = security_sem_semctl(NULL, cmd);
1195 if (err)
1196 return err;
1197 1189
1198 memset(&seminfo, 0, sizeof(seminfo)); 1190 rcu_read_lock();
1199 seminfo.semmni = ns->sc_semmni; 1191 if (cmd == SEM_STAT) {
1200 seminfo.semmns = ns->sc_semmns; 1192 sma = sem_obtain_object(ns, semid);
1201 seminfo.semmsl = ns->sc_semmsl; 1193 if (IS_ERR(sma)) {
1202 seminfo.semopm = ns->sc_semopm; 1194 err = PTR_ERR(sma);
1203 seminfo.semvmx = SEMVMX; 1195 goto out_unlock;
1204 seminfo.semmnu = SEMMNU; 1196 }
1205 seminfo.semmap = SEMMAP; 1197 id = sma->sem_perm.id;
1206 seminfo.semume = SEMUME; 1198 } else {
1207 down_read(&sem_ids(ns).rwsem); 1199 sma = sem_obtain_object_check(ns, semid);
1208 if (cmd == SEM_INFO) { 1200 if (IS_ERR(sma)) {
1209 seminfo.semusz = sem_ids(ns).in_use; 1201 err = PTR_ERR(sma);
1210 seminfo.semaem = ns->used_sems; 1202 goto out_unlock;
1211 } else {
1212 seminfo.semusz = SEMUSZ;
1213 seminfo.semaem = SEMAEM;
1214 } 1203 }
1215 max_id = ipc_get_maxid(&sem_ids(ns));
1216 up_read(&sem_ids(ns).rwsem);
1217 if (copy_to_user(p, &seminfo, sizeof(struct seminfo)))
1218 return -EFAULT;
1219 return (max_id < 0) ? 0 : max_id;
1220 } 1204 }
1221 case IPC_STAT:
1222 case SEM_STAT:
1223 {
1224 struct semid64_ds tbuf;
1225 int id = 0;
1226
1227 memset(&tbuf, 0, sizeof(tbuf));
1228 1205
1229 rcu_read_lock(); 1206 err = -EACCES;
1230 if (cmd == SEM_STAT) { 1207 if (ipcperms(ns, &sma->sem_perm, S_IRUGO))
1231 sma = sem_obtain_object(ns, semid); 1208 goto out_unlock;
1232 if (IS_ERR(sma)) {
1233 err = PTR_ERR(sma);
1234 goto out_unlock;
1235 }
1236 id = sma->sem_perm.id;
1237 } else {
1238 sma = sem_obtain_object_check(ns, semid);
1239 if (IS_ERR(sma)) {
1240 err = PTR_ERR(sma);
1241 goto out_unlock;
1242 }
1243 }
1244 1209
1245 err = -EACCES; 1210 err = security_sem_semctl(sma, cmd);
1246 if (ipcperms(ns, &sma->sem_perm, S_IRUGO)) 1211 if (err)
1247 goto out_unlock; 1212 goto out_unlock;
1248 1213
1249 err = security_sem_semctl(sma, cmd); 1214 kernel_to_ipc64_perm(&sma->sem_perm, &semid64->sem_perm);
1250 if (err) 1215 semid64->sem_otime = get_semotime(sma);
1251 goto out_unlock; 1216 semid64->sem_ctime = sma->sem_ctime;
1217 semid64->sem_nsems = sma->sem_nsems;
1218 rcu_read_unlock();
1219 return id;
1252 1220
1253 kernel_to_ipc64_perm(&sma->sem_perm, &tbuf.sem_perm);
1254 tbuf.sem_otime = get_semotime(sma);
1255 tbuf.sem_ctime = sma->sem_ctime;
1256 tbuf.sem_nsems = sma->sem_nsems;
1257 rcu_read_unlock();
1258 if (copy_semid_to_user(p, &tbuf, version))
1259 return -EFAULT;
1260 return id;
1261 }
1262 default:
1263 return -EINVAL;
1264 }
1265out_unlock: 1221out_unlock:
1266 rcu_read_unlock(); 1222 rcu_read_unlock();
1267 return err; 1223 return err;
1268} 1224}
1269 1225
1226static int semctl_info(struct ipc_namespace *ns, int semid,
1227 int cmd, void __user *p)
1228{
1229 struct seminfo seminfo;
1230 int max_id;
1231 int err;
1232
1233 err = security_sem_semctl(NULL, cmd);
1234 if (err)
1235 return err;
1236
1237 memset(&seminfo, 0, sizeof(seminfo));
1238 seminfo.semmni = ns->sc_semmni;
1239 seminfo.semmns = ns->sc_semmns;
1240 seminfo.semmsl = ns->sc_semmsl;
1241 seminfo.semopm = ns->sc_semopm;
1242 seminfo.semvmx = SEMVMX;
1243 seminfo.semmnu = SEMMNU;
1244 seminfo.semmap = SEMMAP;
1245 seminfo.semume = SEMUME;
1246 down_read(&sem_ids(ns).rwsem);
1247 if (cmd == SEM_INFO) {
1248 seminfo.semusz = sem_ids(ns).in_use;
1249 seminfo.semaem = ns->used_sems;
1250 } else {
1251 seminfo.semusz = SEMUSZ;
1252 seminfo.semaem = SEMAEM;
1253 }
1254 max_id = ipc_get_maxid(&sem_ids(ns));
1255 up_read(&sem_ids(ns).rwsem);
1256 if (copy_to_user(p, &seminfo, sizeof(struct seminfo)))
1257 return -EFAULT;
1258 return (max_id < 0) ? 0 : max_id;
1259}
1260
1270static int semctl_setval(struct ipc_namespace *ns, int semid, int semnum, 1261static int semctl_setval(struct ipc_namespace *ns, int semid, int semnum,
1271 unsigned long arg) 1262 int val)
1272{ 1263{
1273 struct sem_undo *un; 1264 struct sem_undo *un;
1274 struct sem_array *sma; 1265 struct sem_array *sma;
1275 struct sem *curr; 1266 struct sem *curr;
1276 int err, val; 1267 int err;
1277 DEFINE_WAKE_Q(wake_q); 1268 DEFINE_WAKE_Q(wake_q);
1278 1269
1279#if defined(CONFIG_64BIT) && defined(__BIG_ENDIAN)
1280 /* big-endian 64bit */
1281 val = arg >> 32;
1282#else
1283 /* 32bit or little-endian 64bit */
1284 val = arg;
1285#endif
1286
1287 if (val > SEMVMX || val < 0) 1270 if (val > SEMVMX || val < 0)
1288 return -ERANGE; 1271 return -ERANGE;
1289 1272
@@ -1327,7 +1310,7 @@ static int semctl_setval(struct ipc_namespace *ns, int semid, int semnum,
1327 1310
1328 curr->semval = val; 1311 curr->semval = val;
1329 curr->sempid = task_tgid_vnr(current); 1312 curr->sempid = task_tgid_vnr(current);
1330 sma->sem_ctime = get_seconds(); 1313 sma->sem_ctime = ktime_get_real_seconds();
1331 /* maybe some queued-up processes were waiting for this */ 1314 /* maybe some queued-up processes were waiting for this */
1332 do_smart_update(sma, NULL, 0, 0, &wake_q); 1315 do_smart_update(sma, NULL, 0, 0, &wake_q);
1333 sem_unlock(sma, -1); 1316 sem_unlock(sma, -1);
@@ -1455,7 +1438,7 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
1455 for (i = 0; i < nsems; i++) 1438 for (i = 0; i < nsems; i++)
1456 un->semadj[i] = 0; 1439 un->semadj[i] = 0;
1457 } 1440 }
1458 sma->sem_ctime = get_seconds(); 1441 sma->sem_ctime = ktime_get_real_seconds();
1459 /* maybe some queued-up processes were waiting for this */ 1442 /* maybe some queued-up processes were waiting for this */
1460 do_smart_update(sma, NULL, 0, 0, &wake_q); 1443 do_smart_update(sma, NULL, 0, 0, &wake_q);
1461 err = 0; 1444 err = 0;
@@ -1532,23 +1515,17 @@ copy_semid_from_user(struct semid64_ds *out, void __user *buf, int version)
1532 * NOTE: no locks must be held, the rwsem is taken inside this function. 1515 * NOTE: no locks must be held, the rwsem is taken inside this function.
1533 */ 1516 */
1534static int semctl_down(struct ipc_namespace *ns, int semid, 1517static int semctl_down(struct ipc_namespace *ns, int semid,
1535 int cmd, int version, void __user *p) 1518 int cmd, struct semid64_ds *semid64)
1536{ 1519{
1537 struct sem_array *sma; 1520 struct sem_array *sma;
1538 int err; 1521 int err;
1539 struct semid64_ds semid64;
1540 struct kern_ipc_perm *ipcp; 1522 struct kern_ipc_perm *ipcp;
1541 1523
1542 if (cmd == IPC_SET) {
1543 if (copy_semid_from_user(&semid64, p, version))
1544 return -EFAULT;
1545 }
1546
1547 down_write(&sem_ids(ns).rwsem); 1524 down_write(&sem_ids(ns).rwsem);
1548 rcu_read_lock(); 1525 rcu_read_lock();
1549 1526
1550 ipcp = ipcctl_pre_down_nolock(ns, &sem_ids(ns), semid, cmd, 1527 ipcp = ipcctl_pre_down_nolock(ns, &sem_ids(ns), semid, cmd,
1551 &semid64.sem_perm, 0); 1528 &semid64->sem_perm, 0);
1552 if (IS_ERR(ipcp)) { 1529 if (IS_ERR(ipcp)) {
1553 err = PTR_ERR(ipcp); 1530 err = PTR_ERR(ipcp);
1554 goto out_unlock1; 1531 goto out_unlock1;
@@ -1568,10 +1545,10 @@ static int semctl_down(struct ipc_namespace *ns, int semid,
1568 goto out_up; 1545 goto out_up;
1569 case IPC_SET: 1546 case IPC_SET:
1570 sem_lock(sma, NULL, -1); 1547 sem_lock(sma, NULL, -1);
1571 err = ipc_update_perm(&semid64.sem_perm, ipcp); 1548 err = ipc_update_perm(&semid64->sem_perm, ipcp);
1572 if (err) 1549 if (err)
1573 goto out_unlock0; 1550 goto out_unlock0;
1574 sma->sem_ctime = get_seconds(); 1551 sma->sem_ctime = ktime_get_real_seconds();
1575 break; 1552 break;
1576 default: 1553 default:
1577 err = -EINVAL; 1554 err = -EINVAL;
@@ -1592,6 +1569,8 @@ SYSCALL_DEFINE4(semctl, int, semid, int, semnum, int, cmd, unsigned long, arg)
1592 int version; 1569 int version;
1593 struct ipc_namespace *ns; 1570 struct ipc_namespace *ns;
1594 void __user *p = (void __user *)arg; 1571 void __user *p = (void __user *)arg;
1572 struct semid64_ds semid64;
1573 int err;
1595 1574
1596 if (semid < 0) 1575 if (semid < 0)
1597 return -EINVAL; 1576 return -EINVAL;
@@ -1602,9 +1581,15 @@ SYSCALL_DEFINE4(semctl, int, semid, int, semnum, int, cmd, unsigned long, arg)
1602 switch (cmd) { 1581 switch (cmd) {
1603 case IPC_INFO: 1582 case IPC_INFO:
1604 case SEM_INFO: 1583 case SEM_INFO:
1584 return semctl_info(ns, semid, cmd, p);
1605 case IPC_STAT: 1585 case IPC_STAT:
1606 case SEM_STAT: 1586 case SEM_STAT:
1607 return semctl_nolock(ns, semid, cmd, version, p); 1587 err = semctl_stat(ns, semid, cmd, &semid64);
1588 if (err < 0)
1589 return err;
1590 if (copy_semid_to_user(p, &semid64, version))
1591 err = -EFAULT;
1592 return err;
1608 case GETALL: 1593 case GETALL:
1609 case GETVAL: 1594 case GETVAL:
1610 case GETPID: 1595 case GETPID:
@@ -1612,15 +1597,120 @@ SYSCALL_DEFINE4(semctl, int, semid, int, semnum, int, cmd, unsigned long, arg)
1612 case GETZCNT: 1597 case GETZCNT:
1613 case SETALL: 1598 case SETALL:
1614 return semctl_main(ns, semid, semnum, cmd, p); 1599 return semctl_main(ns, semid, semnum, cmd, p);
1600 case SETVAL: {
1601 int val;
1602#if defined(CONFIG_64BIT) && defined(__BIG_ENDIAN)
1603 /* big-endian 64bit */
1604 val = arg >> 32;
1605#else
1606 /* 32bit or little-endian 64bit */
1607 val = arg;
1608#endif
1609 return semctl_setval(ns, semid, semnum, val);
1610 }
1611 case IPC_SET:
1612 if (copy_semid_from_user(&semid64, p, version))
1613 return -EFAULT;
1614 case IPC_RMID:
1615 return semctl_down(ns, semid, cmd, &semid64);
1616 default:
1617 return -EINVAL;
1618 }
1619}
1620
1621#ifdef CONFIG_COMPAT
1622
1623struct compat_semid_ds {
1624 struct compat_ipc_perm sem_perm;
1625 compat_time_t sem_otime;
1626 compat_time_t sem_ctime;
1627 compat_uptr_t sem_base;
1628 compat_uptr_t sem_pending;
1629 compat_uptr_t sem_pending_last;
1630 compat_uptr_t undo;
1631 unsigned short sem_nsems;
1632};
1633
1634static int copy_compat_semid_from_user(struct semid64_ds *out, void __user *buf,
1635 int version)
1636{
1637 memset(out, 0, sizeof(*out));
1638 if (version == IPC_64) {
1639 struct compat_semid64_ds *p = buf;
1640 return get_compat_ipc64_perm(&out->sem_perm, &p->sem_perm);
1641 } else {
1642 struct compat_semid_ds *p = buf;
1643 return get_compat_ipc_perm(&out->sem_perm, &p->sem_perm);
1644 }
1645}
1646
1647static int copy_compat_semid_to_user(void __user *buf, struct semid64_ds *in,
1648 int version)
1649{
1650 if (version == IPC_64) {
1651 struct compat_semid64_ds v;
1652 memset(&v, 0, sizeof(v));
1653 to_compat_ipc64_perm(&v.sem_perm, &in->sem_perm);
1654 v.sem_otime = in->sem_otime;
1655 v.sem_ctime = in->sem_ctime;
1656 v.sem_nsems = in->sem_nsems;
1657 return copy_to_user(buf, &v, sizeof(v));
1658 } else {
1659 struct compat_semid_ds v;
1660 memset(&v, 0, sizeof(v));
1661 to_compat_ipc_perm(&v.sem_perm, &in->sem_perm);
1662 v.sem_otime = in->sem_otime;
1663 v.sem_ctime = in->sem_ctime;
1664 v.sem_nsems = in->sem_nsems;
1665 return copy_to_user(buf, &v, sizeof(v));
1666 }
1667}
1668
1669COMPAT_SYSCALL_DEFINE4(semctl, int, semid, int, semnum, int, cmd, int, arg)
1670{
1671 void __user *p = compat_ptr(arg);
1672 struct ipc_namespace *ns;
1673 struct semid64_ds semid64;
1674 int version = compat_ipc_parse_version(&cmd);
1675 int err;
1676
1677 ns = current->nsproxy->ipc_ns;
1678
1679 if (semid < 0)
1680 return -EINVAL;
1681
1682 switch (cmd & (~IPC_64)) {
1683 case IPC_INFO:
1684 case SEM_INFO:
1685 return semctl_info(ns, semid, cmd, p);
1686 case IPC_STAT:
1687 case SEM_STAT:
1688 err = semctl_stat(ns, semid, cmd, &semid64);
1689 if (err < 0)
1690 return err;
1691 if (copy_compat_semid_to_user(p, &semid64, version))
1692 err = -EFAULT;
1693 return err;
1694 case GETVAL:
1695 case GETPID:
1696 case GETNCNT:
1697 case GETZCNT:
1698 case GETALL:
1699 case SETALL:
1700 return semctl_main(ns, semid, semnum, cmd, p);
1615 case SETVAL: 1701 case SETVAL:
1616 return semctl_setval(ns, semid, semnum, arg); 1702 return semctl_setval(ns, semid, semnum, arg);
1617 case IPC_RMID:
1618 case IPC_SET: 1703 case IPC_SET:
1619 return semctl_down(ns, semid, cmd, version, p); 1704 if (copy_compat_semid_from_user(&semid64, p, version))
1705 return -EFAULT;
1706 /* fallthru */
1707 case IPC_RMID:
1708 return semctl_down(ns, semid, cmd, &semid64);
1620 default: 1709 default:
1621 return -EINVAL; 1710 return -EINVAL;
1622 } 1711 }
1623} 1712}
1713#endif
1624 1714
1625/* If the task doesn't already have a undo_list, then allocate one 1715/* If the task doesn't already have a undo_list, then allocate one
1626 * here. We guarantee there is only one thread using this undo list, 1716 * here. We guarantee there is only one thread using this undo list,
@@ -1766,8 +1856,8 @@ out:
1766 return un; 1856 return un;
1767} 1857}
1768 1858
1769SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops, 1859static long do_semtimedop(int semid, struct sembuf __user *tsops,
1770 unsigned, nsops, const struct timespec __user *, timeout) 1860 unsigned nsops, const struct timespec64 *timeout)
1771{ 1861{
1772 int error = -EINVAL; 1862 int error = -EINVAL;
1773 struct sem_array *sma; 1863 struct sem_array *sma;
@@ -1798,17 +1888,12 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
1798 } 1888 }
1799 1889
1800 if (timeout) { 1890 if (timeout) {
1801 struct timespec _timeout; 1891 if (timeout->tv_sec < 0 || timeout->tv_nsec < 0 ||
1802 if (copy_from_user(&_timeout, timeout, sizeof(*timeout))) { 1892 timeout->tv_nsec >= 1000000000L) {
1803 error = -EFAULT;
1804 goto out_free;
1805 }
1806 if (_timeout.tv_sec < 0 || _timeout.tv_nsec < 0 ||
1807 _timeout.tv_nsec >= 1000000000L) {
1808 error = -EINVAL; 1893 error = -EINVAL;
1809 goto out_free; 1894 goto out_free;
1810 } 1895 }
1811 jiffies_left = timespec_to_jiffies(&_timeout); 1896 jiffies_left = timespec64_to_jiffies(timeout);
1812 } 1897 }
1813 1898
1814 max = 0; 1899 max = 0;
@@ -2023,10 +2108,37 @@ out_free:
2023 return error; 2108 return error;
2024} 2109}
2025 2110
2111SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
2112 unsigned, nsops, const struct timespec __user *, timeout)
2113{
2114 if (timeout) {
2115 struct timespec64 ts;
2116 if (get_timespec64(&ts, timeout))
2117 return -EFAULT;
2118 return do_semtimedop(semid, tsops, nsops, &ts);
2119 }
2120 return do_semtimedop(semid, tsops, nsops, NULL);
2121}
2122
2123#ifdef CONFIG_COMPAT
2124COMPAT_SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsems,
2125 unsigned, nsops,
2126 const struct compat_timespec __user *, timeout)
2127{
2128 if (timeout) {
2129 struct timespec64 ts;
2130 if (compat_get_timespec64(&ts, timeout))
2131 return -EFAULT;
2132 return do_semtimedop(semid, tsems, nsops, &ts);
2133 }
2134 return do_semtimedop(semid, tsems, nsops, NULL);
2135}
2136#endif
2137
2026SYSCALL_DEFINE3(semop, int, semid, struct sembuf __user *, tsops, 2138SYSCALL_DEFINE3(semop, int, semid, struct sembuf __user *, tsops,
2027 unsigned, nsops) 2139 unsigned, nsops)
2028{ 2140{
2029 return sys_semtimedop(semid, tsops, nsops, NULL); 2141 return do_semtimedop(semid, tsops, nsops, NULL);
2030} 2142}
2031 2143
2032/* If CLONE_SYSVSEM is set, establish sharing of SEM_UNDO state between 2144/* If CLONE_SYSVSEM is set, establish sharing of SEM_UNDO state between
@@ -2183,7 +2295,7 @@ static int sysvipc_sem_proc_show(struct seq_file *s, void *it)
2183 struct user_namespace *user_ns = seq_user_ns(s); 2295 struct user_namespace *user_ns = seq_user_ns(s);
2184 struct kern_ipc_perm *ipcp = it; 2296 struct kern_ipc_perm *ipcp = it;
2185 struct sem_array *sma = container_of(ipcp, struct sem_array, sem_perm); 2297 struct sem_array *sma = container_of(ipcp, struct sem_array, sem_perm);
2186 time_t sem_otime; 2298 time64_t sem_otime;
2187 2299
2188 /* 2300 /*
2189 * The proc interface isn't aware of sem_lock(), it calls 2301 * The proc interface isn't aware of sem_lock(), it calls
@@ -2196,7 +2308,7 @@ static int sysvipc_sem_proc_show(struct seq_file *s, void *it)
2196 sem_otime = get_semotime(sma); 2308 sem_otime = get_semotime(sma);
2197 2309
2198 seq_printf(s, 2310 seq_printf(s,
2199 "%10d %10d %4o %10u %5u %5u %5u %5u %10lu %10lu\n", 2311 "%10d %10d %4o %10u %5u %5u %5u %5u %10llu %10llu\n",
2200 sma->sem_perm.key, 2312 sma->sem_perm.key,
2201 sma->sem_perm.id, 2313 sma->sem_perm.id,
2202 sma->sem_perm.mode, 2314 sma->sem_perm.mode,
diff --git a/ipc/shm.c b/ipc/shm.c
index 8fc97beb5234..1b3adfe3c60e 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -202,7 +202,7 @@ static int __shm_open(struct vm_area_struct *vma)
202 if (IS_ERR(shp)) 202 if (IS_ERR(shp))
203 return PTR_ERR(shp); 203 return PTR_ERR(shp);
204 204
205 shp->shm_atim = get_seconds(); 205 shp->shm_atim = ktime_get_real_seconds();
206 shp->shm_lprid = task_tgid_vnr(current); 206 shp->shm_lprid = task_tgid_vnr(current);
207 shp->shm_nattch++; 207 shp->shm_nattch++;
208 shm_unlock(shp); 208 shm_unlock(shp);
@@ -289,7 +289,7 @@ static void shm_close(struct vm_area_struct *vma)
289 goto done; /* no-op */ 289 goto done; /* no-op */
290 290
291 shp->shm_lprid = task_tgid_vnr(current); 291 shp->shm_lprid = task_tgid_vnr(current);
292 shp->shm_dtim = get_seconds(); 292 shp->shm_dtim = ktime_get_real_seconds();
293 shp->shm_nattch--; 293 shp->shm_nattch--;
294 if (shm_may_destroy(ns, shp)) 294 if (shm_may_destroy(ns, shp))
295 shm_destroy(ns, shp); 295 shm_destroy(ns, shp);
@@ -594,7 +594,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
594 shp->shm_cprid = task_tgid_vnr(current); 594 shp->shm_cprid = task_tgid_vnr(current);
595 shp->shm_lprid = 0; 595 shp->shm_lprid = 0;
596 shp->shm_atim = shp->shm_dtim = 0; 596 shp->shm_atim = shp->shm_dtim = 0;
597 shp->shm_ctim = get_seconds(); 597 shp->shm_ctim = ktime_get_real_seconds();
598 shp->shm_segsz = size; 598 shp->shm_segsz = size;
599 shp->shm_nattch = 0; 599 shp->shm_nattch = 0;
600 shp->shm_file = file; 600 shp->shm_file = file;
@@ -815,23 +815,17 @@ static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss,
815 * NOTE: no locks must be held, the rwsem is taken inside this function. 815 * NOTE: no locks must be held, the rwsem is taken inside this function.
816 */ 816 */
817static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd, 817static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd,
818 struct shmid_ds __user *buf, int version) 818 struct shmid64_ds *shmid64)
819{ 819{
820 struct kern_ipc_perm *ipcp; 820 struct kern_ipc_perm *ipcp;
821 struct shmid64_ds shmid64;
822 struct shmid_kernel *shp; 821 struct shmid_kernel *shp;
823 int err; 822 int err;
824 823
825 if (cmd == IPC_SET) {
826 if (copy_shmid_from_user(&shmid64, buf, version))
827 return -EFAULT;
828 }
829
830 down_write(&shm_ids(ns).rwsem); 824 down_write(&shm_ids(ns).rwsem);
831 rcu_read_lock(); 825 rcu_read_lock();
832 826
833 ipcp = ipcctl_pre_down_nolock(ns, &shm_ids(ns), shmid, cmd, 827 ipcp = ipcctl_pre_down_nolock(ns, &shm_ids(ns), shmid, cmd,
834 &shmid64.shm_perm, 0); 828 &shmid64->shm_perm, 0);
835 if (IS_ERR(ipcp)) { 829 if (IS_ERR(ipcp)) {
836 err = PTR_ERR(ipcp); 830 err = PTR_ERR(ipcp);
837 goto out_unlock1; 831 goto out_unlock1;
@@ -851,10 +845,10 @@ static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd,
851 goto out_up; 845 goto out_up;
852 case IPC_SET: 846 case IPC_SET:
853 ipc_lock_object(&shp->shm_perm); 847 ipc_lock_object(&shp->shm_perm);
854 err = ipc_update_perm(&shmid64.shm_perm, ipcp); 848 err = ipc_update_perm(&shmid64->shm_perm, ipcp);
855 if (err) 849 if (err)
856 goto out_unlock0; 850 goto out_unlock0;
857 shp->shm_ctim = get_seconds(); 851 shp->shm_ctim = ktime_get_real_seconds();
858 break; 852 break;
859 default: 853 default:
860 err = -EINVAL; 854 err = -EINVAL;
@@ -870,125 +864,175 @@ out_up:
870 return err; 864 return err;
871} 865}
872 866
873static int shmctl_nolock(struct ipc_namespace *ns, int shmid, 867static int shmctl_ipc_info(struct ipc_namespace *ns,
874 int cmd, int version, void __user *buf) 868 struct shminfo64 *shminfo)
875{ 869{
876 int err; 870 int err = security_shm_shmctl(NULL, IPC_INFO);
877 struct shmid_kernel *shp; 871 if (!err) {
878 872 memset(shminfo, 0, sizeof(*shminfo));
879 /* preliminary security checks for *_INFO */ 873 shminfo->shmmni = shminfo->shmseg = ns->shm_ctlmni;
880 if (cmd == IPC_INFO || cmd == SHM_INFO) { 874 shminfo->shmmax = ns->shm_ctlmax;
881 err = security_shm_shmctl(NULL, cmd); 875 shminfo->shmall = ns->shm_ctlall;
882 if (err) 876 shminfo->shmmin = SHMMIN;
883 return err;
884 }
885
886 switch (cmd) {
887 case IPC_INFO:
888 {
889 struct shminfo64 shminfo;
890
891 memset(&shminfo, 0, sizeof(shminfo));
892 shminfo.shmmni = shminfo.shmseg = ns->shm_ctlmni;
893 shminfo.shmmax = ns->shm_ctlmax;
894 shminfo.shmall = ns->shm_ctlall;
895
896 shminfo.shmmin = SHMMIN;
897 if (copy_shminfo_to_user(buf, &shminfo, version))
898 return -EFAULT;
899
900 down_read(&shm_ids(ns).rwsem); 877 down_read(&shm_ids(ns).rwsem);
901 err = ipc_get_maxid(&shm_ids(ns)); 878 err = ipc_get_maxid(&shm_ids(ns));
902 up_read(&shm_ids(ns).rwsem); 879 up_read(&shm_ids(ns).rwsem);
903
904 if (err < 0) 880 if (err < 0)
905 err = 0; 881 err = 0;
906 goto out;
907 } 882 }
908 case SHM_INFO: 883 return err;
909 { 884}
910 struct shm_info shm_info;
911 885
912 memset(&shm_info, 0, sizeof(shm_info)); 886static int shmctl_shm_info(struct ipc_namespace *ns,
887 struct shm_info *shm_info)
888{
889 int err = security_shm_shmctl(NULL, SHM_INFO);
890 if (!err) {
891 memset(shm_info, 0, sizeof(*shm_info));
913 down_read(&shm_ids(ns).rwsem); 892 down_read(&shm_ids(ns).rwsem);
914 shm_info.used_ids = shm_ids(ns).in_use; 893 shm_info->used_ids = shm_ids(ns).in_use;
915 shm_get_stat(ns, &shm_info.shm_rss, &shm_info.shm_swp); 894 shm_get_stat(ns, &shm_info->shm_rss, &shm_info->shm_swp);
916 shm_info.shm_tot = ns->shm_tot; 895 shm_info->shm_tot = ns->shm_tot;
917 shm_info.swap_attempts = 0; 896 shm_info->swap_attempts = 0;
918 shm_info.swap_successes = 0; 897 shm_info->swap_successes = 0;
919 err = ipc_get_maxid(&shm_ids(ns)); 898 err = ipc_get_maxid(&shm_ids(ns));
920 up_read(&shm_ids(ns).rwsem); 899 up_read(&shm_ids(ns).rwsem);
921 if (copy_to_user(buf, &shm_info, sizeof(shm_info))) { 900 if (err < 0)
922 err = -EFAULT; 901 err = 0;
923 goto out; 902 }
903 return err;
904}
905
906static int shmctl_stat(struct ipc_namespace *ns, int shmid,
907 int cmd, struct shmid64_ds *tbuf)
908{
909 struct shmid_kernel *shp;
910 int result;
911 int err;
912
913 rcu_read_lock();
914 if (cmd == SHM_STAT) {
915 shp = shm_obtain_object(ns, shmid);
916 if (IS_ERR(shp)) {
917 err = PTR_ERR(shp);
918 goto out_unlock;
919 }
920 result = shp->shm_perm.id;
921 } else {
922 shp = shm_obtain_object_check(ns, shmid);
923 if (IS_ERR(shp)) {
924 err = PTR_ERR(shp);
925 goto out_unlock;
924 } 926 }
927 result = 0;
928 }
925 929
926 err = err < 0 ? 0 : err; 930 err = -EACCES;
927 goto out; 931 if (ipcperms(ns, &shp->shm_perm, S_IRUGO))
932 goto out_unlock;
933
934 err = security_shm_shmctl(shp, cmd);
935 if (err)
936 goto out_unlock;
937
938 memset(tbuf, 0, sizeof(*tbuf));
939 kernel_to_ipc64_perm(&shp->shm_perm, &tbuf->shm_perm);
940 tbuf->shm_segsz = shp->shm_segsz;
941 tbuf->shm_atime = shp->shm_atim;
942 tbuf->shm_dtime = shp->shm_dtim;
943 tbuf->shm_ctime = shp->shm_ctim;
944 tbuf->shm_cpid = shp->shm_cprid;
945 tbuf->shm_lpid = shp->shm_lprid;
946 tbuf->shm_nattch = shp->shm_nattch;
947 rcu_read_unlock();
948 return result;
949
950out_unlock:
951 rcu_read_unlock();
952 return err;
953}
954
955static int shmctl_do_lock(struct ipc_namespace *ns, int shmid, int cmd)
956{
957 struct shmid_kernel *shp;
958 struct file *shm_file;
959 int err;
960
961 rcu_read_lock();
962 shp = shm_obtain_object_check(ns, shmid);
963 if (IS_ERR(shp)) {
964 err = PTR_ERR(shp);
965 goto out_unlock1;
928 } 966 }
929 case SHM_STAT:
930 case IPC_STAT:
931 {
932 struct shmid64_ds tbuf;
933 int result;
934
935 rcu_read_lock();
936 if (cmd == SHM_STAT) {
937 shp = shm_obtain_object(ns, shmid);
938 if (IS_ERR(shp)) {
939 err = PTR_ERR(shp);
940 goto out_unlock;
941 }
942 result = shp->shm_perm.id;
943 } else {
944 shp = shm_obtain_object_check(ns, shmid);
945 if (IS_ERR(shp)) {
946 err = PTR_ERR(shp);
947 goto out_unlock;
948 }
949 result = 0;
950 }
951 967
952 err = -EACCES; 968 audit_ipc_obj(&(shp->shm_perm));
953 if (ipcperms(ns, &shp->shm_perm, S_IRUGO)) 969 err = security_shm_shmctl(shp, cmd);
954 goto out_unlock; 970 if (err)
971 goto out_unlock1;
955 972
956 err = security_shm_shmctl(shp, cmd); 973 ipc_lock_object(&shp->shm_perm);
957 if (err)
958 goto out_unlock;
959 974
960 memset(&tbuf, 0, sizeof(tbuf)); 975 /* check if shm_destroy() is tearing down shp */
961 kernel_to_ipc64_perm(&shp->shm_perm, &tbuf.shm_perm); 976 if (!ipc_valid_object(&shp->shm_perm)) {
962 tbuf.shm_segsz = shp->shm_segsz; 977 err = -EIDRM;
963 tbuf.shm_atime = shp->shm_atim; 978 goto out_unlock0;
964 tbuf.shm_dtime = shp->shm_dtim;
965 tbuf.shm_ctime = shp->shm_ctim;
966 tbuf.shm_cpid = shp->shm_cprid;
967 tbuf.shm_lpid = shp->shm_lprid;
968 tbuf.shm_nattch = shp->shm_nattch;
969 rcu_read_unlock();
970
971 if (copy_shmid_to_user(buf, &tbuf, version))
972 err = -EFAULT;
973 else
974 err = result;
975 goto out;
976 } 979 }
977 default: 980
978 return -EINVAL; 981 if (!ns_capable(ns->user_ns, CAP_IPC_LOCK)) {
982 kuid_t euid = current_euid();
983
984 if (!uid_eq(euid, shp->shm_perm.uid) &&
985 !uid_eq(euid, shp->shm_perm.cuid)) {
986 err = -EPERM;
987 goto out_unlock0;
988 }
989 if (cmd == SHM_LOCK && !rlimit(RLIMIT_MEMLOCK)) {
990 err = -EPERM;
991 goto out_unlock0;
992 }
979 } 993 }
980 994
981out_unlock: 995 shm_file = shp->shm_file;
996 if (is_file_hugepages(shm_file))
997 goto out_unlock0;
998
999 if (cmd == SHM_LOCK) {
1000 struct user_struct *user = current_user();
1001
1002 err = shmem_lock(shm_file, 1, user);
1003 if (!err && !(shp->shm_perm.mode & SHM_LOCKED)) {
1004 shp->shm_perm.mode |= SHM_LOCKED;
1005 shp->mlock_user = user;
1006 }
1007 goto out_unlock0;
1008 }
1009
1010 /* SHM_UNLOCK */
1011 if (!(shp->shm_perm.mode & SHM_LOCKED))
1012 goto out_unlock0;
1013 shmem_lock(shm_file, 0, shp->mlock_user);
1014 shp->shm_perm.mode &= ~SHM_LOCKED;
1015 shp->mlock_user = NULL;
1016 get_file(shm_file);
1017 ipc_unlock_object(&shp->shm_perm);
1018 rcu_read_unlock();
1019 shmem_unlock_mapping(shm_file->f_mapping);
1020
1021 fput(shm_file);
1022 return err;
1023
1024out_unlock0:
1025 ipc_unlock_object(&shp->shm_perm);
1026out_unlock1:
982 rcu_read_unlock(); 1027 rcu_read_unlock();
983out:
984 return err; 1028 return err;
985} 1029}
986 1030
987SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf) 1031SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
988{ 1032{
989 struct shmid_kernel *shp;
990 int err, version; 1033 int err, version;
991 struct ipc_namespace *ns; 1034 struct ipc_namespace *ns;
1035 struct shmid64_ds sem64;
992 1036
993 if (cmd < 0 || shmid < 0) 1037 if (cmd < 0 || shmid < 0)
994 return -EINVAL; 1038 return -EINVAL;
@@ -997,92 +1041,222 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
997 ns = current->nsproxy->ipc_ns; 1041 ns = current->nsproxy->ipc_ns;
998 1042
999 switch (cmd) { 1043 switch (cmd) {
1000 case IPC_INFO: 1044 case IPC_INFO: {
1001 case SHM_INFO: 1045 struct shminfo64 shminfo;
1046 err = shmctl_ipc_info(ns, &shminfo);
1047 if (err < 0)
1048 return err;
1049 if (copy_shminfo_to_user(buf, &shminfo, version))
1050 err = -EFAULT;
1051 return err;
1052 }
1053 case SHM_INFO: {
1054 struct shm_info shm_info;
1055 err = shmctl_shm_info(ns, &shm_info);
1056 if (err < 0)
1057 return err;
1058 if (copy_to_user(buf, &shm_info, sizeof(shm_info)))
1059 err = -EFAULT;
1060 return err;
1061 }
1002 case SHM_STAT: 1062 case SHM_STAT:
1003 case IPC_STAT: 1063 case IPC_STAT: {
1004 return shmctl_nolock(ns, shmid, cmd, version, buf); 1064 err = shmctl_stat(ns, shmid, cmd, &sem64);
1005 case IPC_RMID: 1065 if (err < 0)
1066 return err;
1067 if (copy_shmid_to_user(buf, &sem64, version))
1068 err = -EFAULT;
1069 return err;
1070 }
1006 case IPC_SET: 1071 case IPC_SET:
1007 return shmctl_down(ns, shmid, cmd, buf, version); 1072 if (copy_shmid_from_user(&sem64, buf, version))
1073 return -EFAULT;
1074 /* fallthru */
1075 case IPC_RMID:
1076 return shmctl_down(ns, shmid, cmd, &sem64);
1008 case SHM_LOCK: 1077 case SHM_LOCK:
1009 case SHM_UNLOCK: 1078 case SHM_UNLOCK:
1010 { 1079 return shmctl_do_lock(ns, shmid, cmd);
1011 struct file *shm_file; 1080 default:
1081 return -EINVAL;
1082 }
1083}
1012 1084
1013 rcu_read_lock(); 1085#ifdef CONFIG_COMPAT
1014 shp = shm_obtain_object_check(ns, shmid); 1086
1015 if (IS_ERR(shp)) { 1087struct compat_shmid_ds {
1016 err = PTR_ERR(shp); 1088 struct compat_ipc_perm shm_perm;
1017 goto out_unlock1; 1089 int shm_segsz;
1018 } 1090 compat_time_t shm_atime;
1091 compat_time_t shm_dtime;
1092 compat_time_t shm_ctime;
1093 compat_ipc_pid_t shm_cpid;
1094 compat_ipc_pid_t shm_lpid;
1095 unsigned short shm_nattch;
1096 unsigned short shm_unused;
1097 compat_uptr_t shm_unused2;
1098 compat_uptr_t shm_unused3;
1099};
1019 1100
1020 audit_ipc_obj(&(shp->shm_perm)); 1101struct compat_shminfo64 {
1021 err = security_shm_shmctl(shp, cmd); 1102 compat_ulong_t shmmax;
1022 if (err) 1103 compat_ulong_t shmmin;
1023 goto out_unlock1; 1104 compat_ulong_t shmmni;
1105 compat_ulong_t shmseg;
1106 compat_ulong_t shmall;
1107 compat_ulong_t __unused1;
1108 compat_ulong_t __unused2;
1109 compat_ulong_t __unused3;
1110 compat_ulong_t __unused4;
1111};
1024 1112
1025 ipc_lock_object(&shp->shm_perm); 1113struct compat_shm_info {
1114 compat_int_t used_ids;
1115 compat_ulong_t shm_tot, shm_rss, shm_swp;
1116 compat_ulong_t swap_attempts, swap_successes;
1117};
1026 1118
1027 /* check if shm_destroy() is tearing down shp */ 1119static int copy_compat_shminfo_to_user(void __user *buf, struct shminfo64 *in,
1028 if (!ipc_valid_object(&shp->shm_perm)) { 1120 int version)
1029 err = -EIDRM; 1121{
1030 goto out_unlock0; 1122 if (in->shmmax > INT_MAX)
1031 } 1123 in->shmmax = INT_MAX;
1124 if (version == IPC_64) {
1125 struct compat_shminfo64 info;
1126 memset(&info, 0, sizeof(info));
1127 info.shmmax = in->shmmax;
1128 info.shmmin = in->shmmin;
1129 info.shmmni = in->shmmni;
1130 info.shmseg = in->shmseg;
1131 info.shmall = in->shmall;
1132 return copy_to_user(buf, &info, sizeof(info));
1133 } else {
1134 struct shminfo info;
1135 memset(&info, 0, sizeof(info));
1136 info.shmmax = in->shmmax;
1137 info.shmmin = in->shmmin;
1138 info.shmmni = in->shmmni;
1139 info.shmseg = in->shmseg;
1140 info.shmall = in->shmall;
1141 return copy_to_user(buf, &info, sizeof(info));
1142 }
1143}
1032 1144
1033 if (!ns_capable(ns->user_ns, CAP_IPC_LOCK)) { 1145static int put_compat_shm_info(struct shm_info *ip,
1034 kuid_t euid = current_euid(); 1146 struct compat_shm_info __user *uip)
1035 1147{
1036 if (!uid_eq(euid, shp->shm_perm.uid) && 1148 struct compat_shm_info info;
1037 !uid_eq(euid, shp->shm_perm.cuid)) { 1149
1038 err = -EPERM; 1150 memset(&info, 0, sizeof(info));
1039 goto out_unlock0; 1151 info.used_ids = ip->used_ids;
1040 } 1152 info.shm_tot = ip->shm_tot;
1041 if (cmd == SHM_LOCK && !rlimit(RLIMIT_MEMLOCK)) { 1153 info.shm_rss = ip->shm_rss;
1042 err = -EPERM; 1154 info.shm_swp = ip->shm_swp;
1043 goto out_unlock0; 1155 info.swap_attempts = ip->swap_attempts;
1044 } 1156 info.swap_successes = ip->swap_successes;
1045 } 1157 return copy_to_user(up, &info, sizeof(info));
1158}
1046 1159
1047 shm_file = shp->shm_file; 1160static int copy_compat_shmid_to_user(void __user *buf, struct shmid64_ds *in,
1048 if (is_file_hugepages(shm_file)) 1161 int version)
1049 goto out_unlock0; 1162{
1163 if (version == IPC_64) {
1164 struct compat_shmid64_ds v;
1165 memset(&v, 0, sizeof(v));
1166 to_compat_ipc64_perm(&v.shm_perm, &in->shm_perm);
1167 v.shm_atime = in->shm_atime;
1168 v.shm_dtime = in->shm_dtime;
1169 v.shm_ctime = in->shm_ctime;
1170 v.shm_segsz = in->shm_segsz;
1171 v.shm_nattch = in->shm_nattch;
1172 v.shm_cpid = in->shm_cpid;
1173 v.shm_lpid = in->shm_lpid;
1174 return copy_to_user(buf, &v, sizeof(v));
1175 } else {
1176 struct compat_shmid_ds v;
1177 memset(&v, 0, sizeof(v));
1178 to_compat_ipc_perm(&v.shm_perm, &in->shm_perm);
1179 v.shm_perm.key = in->shm_perm.key;
1180 v.shm_atime = in->shm_atime;
1181 v.shm_dtime = in->shm_dtime;
1182 v.shm_ctime = in->shm_ctime;
1183 v.shm_segsz = in->shm_segsz;
1184 v.shm_nattch = in->shm_nattch;
1185 v.shm_cpid = in->shm_cpid;
1186 v.shm_lpid = in->shm_lpid;
1187 return copy_to_user(buf, &v, sizeof(v));
1188 }
1189}
1050 1190
1051 if (cmd == SHM_LOCK) { 1191static int copy_compat_shmid_from_user(struct shmid64_ds *out, void __user *buf,
1052 struct user_struct *user = current_user(); 1192 int version)
1193{
1194 memset(out, 0, sizeof(*out));
1195 if (version == IPC_64) {
1196 struct compat_shmid64_ds *p = buf;
1197 return get_compat_ipc64_perm(&out->shm_perm, &p->shm_perm);
1198 } else {
1199 struct compat_shmid_ds *p = buf;
1200 return get_compat_ipc_perm(&out->shm_perm, &p->shm_perm);
1201 }
1202}
1053 1203
1054 err = shmem_lock(shm_file, 1, user); 1204COMPAT_SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, void __user *, uptr)
1055 if (!err && !(shp->shm_perm.mode & SHM_LOCKED)) { 1205{
1056 shp->shm_perm.mode |= SHM_LOCKED; 1206 struct ipc_namespace *ns;
1057 shp->mlock_user = user; 1207 struct shmid64_ds sem64;
1058 } 1208 int version = compat_ipc_parse_version(&cmd);
1059 goto out_unlock0; 1209 int err;
1060 }
1061 1210
1062 /* SHM_UNLOCK */ 1211 ns = current->nsproxy->ipc_ns;
1063 if (!(shp->shm_perm.mode & SHM_LOCKED)) 1212
1064 goto out_unlock0; 1213 if (cmd < 0 || shmid < 0)
1065 shmem_lock(shm_file, 0, shp->mlock_user); 1214 return -EINVAL;
1066 shp->shm_perm.mode &= ~SHM_LOCKED;
1067 shp->mlock_user = NULL;
1068 get_file(shm_file);
1069 ipc_unlock_object(&shp->shm_perm);
1070 rcu_read_unlock();
1071 shmem_unlock_mapping(shm_file->f_mapping);
1072 1215
1073 fput(shm_file); 1216 switch (cmd) {
1217 case IPC_INFO: {
1218 struct shminfo64 shminfo;
1219 err = shmctl_ipc_info(ns, &shminfo);
1220 if (err < 0)
1221 return err;
1222 if (copy_compat_shminfo_to_user(uptr, &shminfo, version))
1223 err = -EFAULT;
1224 return err;
1225 }
1226 case SHM_INFO: {
1227 struct shm_info shm_info;
1228 err = shmctl_shm_info(ns, &shm_info);
1229 if (err < 0)
1230 return err;
1231 if (put_compat_shm_info(&shm_info, uptr))
1232 err = -EFAULT;
1074 return err; 1233 return err;
1075 } 1234 }
1235 case IPC_STAT:
1236 case SHM_STAT:
1237 err = shmctl_stat(ns, shmid, cmd, &sem64);
1238 if (err < 0)
1239 return err;
1240 if (copy_compat_shmid_to_user(&sem64, uptr, version))
1241 err = -EFAULT;
1242 return err;
1243
1244 case IPC_SET:
1245 if (copy_compat_shmid_from_user(&sem64, uptr, version))
1246 return -EFAULT;
1247 /* fallthru */
1248 case IPC_RMID:
1249 return shmctl_down(ns, shmid, cmd, &sem64);
1250 case SHM_LOCK:
1251 case SHM_UNLOCK:
1252 return shmctl_do_lock(ns, shmid, cmd);
1253 break;
1076 default: 1254 default:
1077 return -EINVAL; 1255 return -EINVAL;
1078 } 1256 }
1079
1080out_unlock0:
1081 ipc_unlock_object(&shp->shm_perm);
1082out_unlock1:
1083 rcu_read_unlock();
1084 return err; 1257 return err;
1085} 1258}
1259#endif
1086 1260
1087/* 1261/*
1088 * Fix shmaddr, allocate descriptor, map shm, add attach descriptor to lists. 1262 * Fix shmaddr, allocate descriptor, map shm, add attach descriptor to lists.
@@ -1267,6 +1441,25 @@ SYSCALL_DEFINE3(shmat, int, shmid, char __user *, shmaddr, int, shmflg)
1267 return (long)ret; 1441 return (long)ret;
1268} 1442}
1269 1443
1444#ifdef CONFIG_COMPAT
1445
1446#ifndef COMPAT_SHMLBA
1447#define COMPAT_SHMLBA SHMLBA
1448#endif
1449
1450COMPAT_SYSCALL_DEFINE3(shmat, int, shmid, compat_uptr_t, shmaddr, int, shmflg)
1451{
1452 unsigned long ret;
1453 long err;
1454
1455 err = do_shmat(shmid, compat_ptr(shmaddr), shmflg, &ret, COMPAT_SHMLBA);
1456 if (err)
1457 return err;
1458 force_successful_syscall_return();
1459 return (long)ret;
1460}
1461#endif
1462
1270/* 1463/*
1271 * detach and kill segment if marked destroyed. 1464 * detach and kill segment if marked destroyed.
1272 * The work is done in shm_close. 1465 * The work is done in shm_close.
@@ -1397,7 +1590,7 @@ static int sysvipc_shm_proc_show(struct seq_file *s, void *it)
1397 1590
1398 seq_printf(s, 1591 seq_printf(s,
1399 "%10d %10d %4o " SIZE_SPEC " %5u %5u " 1592 "%10d %10d %4o " SIZE_SPEC " %5u %5u "
1400 "%5lu %5u %5u %5u %5u %10lu %10lu %10lu " 1593 "%5lu %5u %5u %5u %5u %10llu %10llu %10llu "
1401 SIZE_SPEC " " SIZE_SPEC "\n", 1594 SIZE_SPEC " " SIZE_SPEC "\n",
1402 shp->shm_perm.key, 1595 shp->shm_perm.key,
1403 shp->shm_perm.id, 1596 shp->shm_perm.id,
diff --git a/ipc/syscall.c b/ipc/syscall.c
index 52429489cde0..667022746ca5 100644
--- a/ipc/syscall.c
+++ b/ipc/syscall.c
@@ -5,12 +5,12 @@
5 * the individual syscalls instead. 5 * the individual syscalls instead.
6 */ 6 */
7#include <linux/unistd.h> 7#include <linux/unistd.h>
8#include <linux/syscalls.h>
8 9
9#ifdef __ARCH_WANT_SYS_IPC 10#ifdef __ARCH_WANT_SYS_IPC
10#include <linux/errno.h> 11#include <linux/errno.h>
11#include <linux/ipc.h> 12#include <linux/ipc.h>
12#include <linux/shm.h> 13#include <linux/shm.h>
13#include <linux/syscalls.h>
14#include <linux/uaccess.h> 14#include <linux/uaccess.h>
15 15
16SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second, 16SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second,
@@ -97,3 +97,91 @@ SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second,
97 } 97 }
98} 98}
99#endif 99#endif
100
101#ifdef CONFIG_COMPAT
102#include <linux/compat.h>
103
104#ifndef COMPAT_SHMLBA
105#define COMPAT_SHMLBA SHMLBA
106#endif
107
108struct compat_ipc_kludge {
109 compat_uptr_t msgp;
110 compat_long_t msgtyp;
111};
112
113#ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC
114COMPAT_SYSCALL_DEFINE6(ipc, u32, call, int, first, int, second,
115 u32, third, compat_uptr_t, ptr, u32, fifth)
116{
117 int version;
118 u32 pad;
119
120 version = call >> 16; /* hack for backward compatibility */
121 call &= 0xffff;
122
123 switch (call) {
124 case SEMOP:
125 /* struct sembuf is the same on 32 and 64bit :)) */
126 return sys_semtimedop(first, compat_ptr(ptr), second, NULL);
127 case SEMTIMEDOP:
128 return compat_sys_semtimedop(first, compat_ptr(ptr), second,
129 compat_ptr(fifth));
130 case SEMGET:
131 return sys_semget(first, second, third);
132 case SEMCTL:
133 if (!ptr)
134 return -EINVAL;
135 if (get_user(pad, (u32 __user *) compat_ptr(ptr)))
136 return -EFAULT;
137 return compat_sys_semctl(first, second, third, pad);
138
139 case MSGSND:
140 return compat_sys_msgsnd(first, ptr, second, third);
141
142 case MSGRCV: {
143 void __user *uptr = compat_ptr(ptr);
144
145 if (first < 0 || second < 0)
146 return -EINVAL;
147
148 if (!version) {
149 struct compat_ipc_kludge ipck;
150 if (!uptr)
151 return -EINVAL;
152 if (copy_from_user(&ipck, uptr, sizeof(ipck)))
153 return -EFAULT;
154 return compat_sys_msgrcv(first, ipck.msgp, second,
155 ipck.msgtyp, third);
156 }
157 return compat_sys_msgrcv(first, ptr, second, fifth, third);
158 }
159 case MSGGET:
160 return sys_msgget(first, second);
161 case MSGCTL:
162 return compat_sys_msgctl(first, second, compat_ptr(ptr));
163
164 case SHMAT: {
165 int err;
166 unsigned long raddr;
167
168 if (version == 1)
169 return -EINVAL;
170 err = do_shmat(first, compat_ptr(ptr), second, &raddr,
171 COMPAT_SHMLBA);
172 if (err < 0)
173 return err;
174 return put_user(raddr, (compat_ulong_t *)compat_ptr(third));
175 }
176 case SHMDT:
177 return sys_shmdt(compat_ptr(ptr));
178 case SHMGET:
179 return sys_shmget(first, (unsigned)second, third);
180 case SHMCTL:
181 return compat_sys_shmctl(first, second, compat_ptr(ptr));
182 }
183
184 return -ENOSYS;
185}
186#endif
187#endif
diff --git a/ipc/util.h b/ipc/util.h
index 80c9f51c3f07..b21297bc11eb 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -194,4 +194,34 @@ int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids,
194 const struct ipc_ops *ops, struct ipc_params *params); 194 const struct ipc_ops *ops, struct ipc_params *params);
195void free_ipcs(struct ipc_namespace *ns, struct ipc_ids *ids, 195void free_ipcs(struct ipc_namespace *ns, struct ipc_ids *ids,
196 void (*free)(struct ipc_namespace *, struct kern_ipc_perm *)); 196 void (*free)(struct ipc_namespace *, struct kern_ipc_perm *));
197
198#ifdef CONFIG_COMPAT
199#include <linux/compat.h>
200struct compat_ipc_perm {
201 key_t key;
202 __compat_uid_t uid;
203 __compat_gid_t gid;
204 __compat_uid_t cuid;
205 __compat_gid_t cgid;
206 compat_mode_t mode;
207 unsigned short seq;
208};
209
210void to_compat_ipc_perm(struct compat_ipc_perm *, struct ipc64_perm *);
211void to_compat_ipc64_perm(struct compat_ipc64_perm *, struct ipc64_perm *);
212int get_compat_ipc_perm(struct ipc64_perm *, struct compat_ipc_perm __user *);
213int get_compat_ipc64_perm(struct ipc64_perm *,
214 struct compat_ipc64_perm __user *);
215
216static inline int compat_ipc_parse_version(int *cmd)
217{
218#ifdef CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION
219 int version = *cmd & IPC_64;
220 *cmd &= ~IPC_64;
221 return version;
222#else
223 return IPC_64;
224#endif
225}
226#endif
197#endif 227#endif
diff --git a/kernel/audit.h b/kernel/audit.h
index b331d9b83f63..9b110ae17ee3 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -182,7 +182,7 @@ struct audit_context {
182 mqd_t mqdes; 182 mqd_t mqdes;
183 size_t msg_len; 183 size_t msg_len;
184 unsigned int msg_prio; 184 unsigned int msg_prio;
185 struct timespec abs_timeout; 185 struct timespec64 abs_timeout;
186 } mq_sendrecv; 186 } mq_sendrecv;
187 struct { 187 struct {
188 int oflag; 188 int oflag;
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index aac1a41f82bd..ecc23e25c9eb 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -1235,11 +1235,11 @@ static void show_special(struct audit_context *context, int *call_panic)
1235 case AUDIT_MQ_SENDRECV: 1235 case AUDIT_MQ_SENDRECV:
1236 audit_log_format(ab, 1236 audit_log_format(ab,
1237 "mqdes=%d msg_len=%zd msg_prio=%u " 1237 "mqdes=%d msg_len=%zd msg_prio=%u "
1238 "abs_timeout_sec=%ld abs_timeout_nsec=%ld", 1238 "abs_timeout_sec=%lld abs_timeout_nsec=%ld",
1239 context->mq_sendrecv.mqdes, 1239 context->mq_sendrecv.mqdes,
1240 context->mq_sendrecv.msg_len, 1240 context->mq_sendrecv.msg_len,
1241 context->mq_sendrecv.msg_prio, 1241 context->mq_sendrecv.msg_prio,
1242 context->mq_sendrecv.abs_timeout.tv_sec, 1242 (long long) context->mq_sendrecv.abs_timeout.tv_sec,
1243 context->mq_sendrecv.abs_timeout.tv_nsec); 1243 context->mq_sendrecv.abs_timeout.tv_nsec);
1244 break; 1244 break;
1245 case AUDIT_MQ_NOTIFY: 1245 case AUDIT_MQ_NOTIFY:
@@ -2083,15 +2083,15 @@ void __audit_mq_open(int oflag, umode_t mode, struct mq_attr *attr)
2083 * 2083 *
2084 */ 2084 */
2085void __audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, 2085void __audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio,
2086 const struct timespec *abs_timeout) 2086 const struct timespec64 *abs_timeout)
2087{ 2087{
2088 struct audit_context *context = current->audit_context; 2088 struct audit_context *context = current->audit_context;
2089 struct timespec *p = &context->mq_sendrecv.abs_timeout; 2089 struct timespec64 *p = &context->mq_sendrecv.abs_timeout;
2090 2090
2091 if (abs_timeout) 2091 if (abs_timeout)
2092 memcpy(p, abs_timeout, sizeof(struct timespec)); 2092 memcpy(p, abs_timeout, sizeof(*p));
2093 else 2093 else
2094 memset(p, 0, sizeof(struct timespec)); 2094 memset(p, 0, sizeof(*p));
2095 2095
2096 context->mq_sendrecv.mqdes = mqdes; 2096 context->mq_sendrecv.mqdes = mqdes;
2097 context->mq_sendrecv.msg_len = msg_len; 2097 context->mq_sendrecv.msg_len = msg_len;
diff --git a/kernel/compat.c b/kernel/compat.c
index 6f0a0e723a06..772e038d04d9 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -200,29 +200,6 @@ int compat_put_timespec(const struct timespec *ts, void __user *uts)
200} 200}
201EXPORT_SYMBOL_GPL(compat_put_timespec); 201EXPORT_SYMBOL_GPL(compat_put_timespec);
202 202
203int compat_convert_timespec(struct timespec __user **kts,
204 const void __user *cts)
205{
206 struct timespec ts;
207 struct timespec __user *uts;
208
209 if (!cts || COMPAT_USE_64BIT_TIME) {
210 *kts = (struct timespec __user *)cts;
211 return 0;
212 }
213
214 uts = compat_alloc_user_space(sizeof(ts));
215 if (!uts)
216 return -EFAULT;
217 if (compat_get_timespec(&ts, cts))
218 return -EFAULT;
219 if (copy_to_user(uts, &ts, sizeof(ts)))
220 return -EFAULT;
221
222 *kts = uts;
223 return 0;
224}
225
226int get_compat_itimerval(struct itimerval *o, const struct compat_itimerval __user *i) 203int get_compat_itimerval(struct itimerval *o, const struct compat_itimerval __user *i)
227{ 204{
228 struct compat_itimerval v32; 205 struct compat_itimerval v32;