History

Merge branch 'work.ipc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull ipc compat cleanup and 64-bit time_t from Al Viro: "IPC copyin/copyout sanitizing, including 64bit time_t work from Deepa Dinamani" * 'work.ipc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: utimes: Make utimes y2038 safe ipc: shm: Make shmid_kernel timestamps y2038 safe ipc: sem: Make sem_array timestamps y2038 safe ipc: msg: Make msg_queue timestamps y2038 safe ipc: mqueue: Replace timespec with timespec64 ipc: Make sys_semtimedop() y2038 safe get rid of SYSVIPC_COMPAT on ia64 semtimedop(): move compat to native shmat(2): move compat to native msgrcv(2), msgsnd(2): move compat to native ipc(2): move compat to native ipc: make use of compat ipc_perm helpers semctl(): move compat to native semctl(): separate all layout-dependent copyin/copyout msgctl(): move compat to native msgctl(): split the actual work from copyin/copyout ipc: move compat shmctl to native shmctl: split the work from copyin/copyout

Linus Torvalds committed 9 years ago

Commit cc73fee2 parents e7cdb60 aaed2dd19 files · +1044 −1195Browse files

Unified · Split

19 files
  1. arch/ia64/Kconfig.debug +0 −5
  2. fs/utimes.c +12 −11
  3. include/linux/audit.h +3 −3
  4. include/linux/compat.h +0 −9
  5. include/linux/msg.h +4 −11
  6. include/linux/sem.h +2 −1
  7. include/linux/shm.h +3 −3
  8. include/linux/time.h +1 −1
  9. init/initramfs.c +1 −1
  10. ipc/compat.c +32 −708
  11. ipc/mqueue.c +14 −14
  12. ipc/msg.c +255 −111
  13. ipc/sem.c +228 −116
  14. ipc/shm.c +363 −170
  15. ipc/syscall.c +89 −1
  16. ipc/util.h +30 −0
  17. kernel/audit.h +1 −1
  18. kernel/auditsc.c +6 −6
  19. kernel/compat.c +0 −23
arch/ia64/Kconfig.debug+0−5
@@ -56,9 +56,4 @@ config IA64_DEBUG_IRQ · 55 unmodified lines
5656 and restore instructions. It's useful for tracking down spinlock
5757 problems, but slow! If you're unsure, select N.
5858
59−config SYSVIPC_COMPAT
60− bool
61− depends on COMPAT && SYSVIPC
62− default y
63−
6459 endmenu
fs/utimes.c+12−11
@@ -22,7 +22,7 @@ · 21 unmodified lines
2222 */
2323 SYSCALL_DEFINE2(utime, char __user *, filename, struct utimbuf __user *, times)
2424 {
25− struct timespec tv[2];
25+ struct timespec64 tv[2];
2626
2727 if (times) {
2828 if (get_user(tv[0].tv_sec, &times->actime) ||
@@ -44,7 +44,7 @@ static bool nsec_valid(long nsec) · 15 unmodified lines
4444 return nsec >= 0 && nsec <= 999999999;
4545 }
4646
47−static int utimes_common(const struct path *path, struct timespec *times)
47+static int utimes_common(const struct path *path, struct timespec64 *times)
4848 {
4949 int error;
5050 struct iattr newattrs;
@@ -115,7 +115,7 @@ out: · 64 unmodified lines
115115 * must be owner or have write permission.
116116 * Else, update from *times, must be owner or super user.
117117 */
118−long do_utimes(int dfd, const char __user *filename, struct timespec *times,
118+long do_utimes(int dfd, const char __user *filename, struct timespec64 *times,
119119 int flags)
120120 {
121121 int error = -EINVAL;
@@ -167,10 +167,11 @@ out: · 45 unmodified lines
167167 SYSCALL_DEFINE4(utimensat, int, dfd, const char __user *, filename,
168168 struct timespec __user *, utimes, int, flags)
169169 {
170− struct timespec tstimes[2];
170+ struct timespec64 tstimes[2];
171171
172172 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])))
174175 return -EFAULT;
175176
176177 /* Nothing to do, we must not even check the path. */
@@ -186,7 +187,7 @@ SYSCALL_DEFINE3(futimesat, int, dfd, const char __user *, filename, · 9 unmodified lines
186187 struct timeval __user *, utimes)
187188 {
188189 struct timeval times[2];
189− struct timespec tstimes[2];
190+ struct timespec64 tstimes[2];
190191
191192 if (utimes) {
192193 if (copy_from_user(&times, utimes, sizeof(times)))
@@ -224,7 +225,7 @@ SYSCALL_DEFINE2(utimes, char __user *, filename, · 31 unmodified lines
224225 COMPAT_SYSCALL_DEFINE2(utime, const char __user *, filename,
225226 struct compat_utimbuf __user *, t)
226227 {
227− struct timespec tv[2];
228+ struct timespec64 tv[2];
228229
229230 if (t) {
230231 if (get_user(tv[0].tv_sec, &t->actime) ||
@@ -238,11 +239,11 @@ COMPAT_SYSCALL_DEFINE2(utime, const char __user *, filename, · 7 unmodified lines
238239
239240 COMPAT_SYSCALL_DEFINE4(utimensat, unsigned int, dfd, const char __user *, filename, struct compat_timespec __user *, t, int, flags)
240241 {
241− struct timespec tv[2];
242+ struct timespec64 tv[2];
242243
243244 if (t) {
244− if (compat_get_timespec(&tv[0], &t[0]) ||
245− compat_get_timespec(&tv[1], &t[1]))
245+ if (compat_get_timespec64(&tv[0], &t[0]) ||
246+ compat_get_timespec64(&tv[1], &t[1]))
246247 return -EFAULT;
247248
248249 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 · 4 unmodified lines
253254
254255 COMPAT_SYSCALL_DEFINE3(futimesat, unsigned int, dfd, const char __user *, filename, struct compat_timeval __user *, t)
255256 {
256− struct timespec tv[2];
257+ struct timespec64 tv[2];
257258
258259 if (t) {
259260 if (get_user(tv[0].tv_sec, &t[0].tv_sec) ||
include/linux/audit.h+3−3
@@ -351,7 +351,7 @@ extern int __audit_socketcall(int nargs, unsigned long *args); · 350 unmodified lines
351351 extern int __audit_sockaddr(int len, void *addr);
352352 extern void __audit_fd_pair(int fd1, int fd2);
353353 extern void __audit_mq_open(int oflag, umode_t mode, struct mq_attr *attr);
354−extern void __audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec *abs_timeout);
354+extern void __audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec64 *abs_timeout);
355355 extern void __audit_mq_notify(mqd_t mqdes, const struct sigevent *notification);
356356 extern void __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat);
357357 extern 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) · 54 unmodified lines
412412 if (unlikely(!audit_dummy_context()))
413413 __audit_mq_open(oflag, mode, attr);
414414 }
415−static inline void audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec *abs_timeout)
415+static inline void audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec64 *abs_timeout)
416416 {
417417 if (unlikely(!audit_dummy_context()))
418418 __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) · 130 unmodified lines
549549 { }
550550 static inline void audit_mq_sendrecv(mqd_t mqdes, size_t msg_len,
551551 unsigned int msg_prio,
552− const struct timespec *abs_timeout)
552+ const struct timespec64 *abs_timeout)
553553 { }
554554 static inline void audit_mq_notify(mqd_t mqdes,
555555 const struct sigevent *notification)
include/linux/compat.h+0−9
@@ -171,15 +171,6 @@ extern int get_compat_itimerspec64(struct itimerspec64 *its, · 170 unmodified lines
171171 extern int put_compat_itimerspec64(const struct itimerspec64 *its,
172172 struct compat_itimerspec __user *uits);
173173
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− */
180−extern int compat_convert_timespec(struct timespec __user **,
181− const void __user *);
182−
183174 struct compat_iovec {
184175 compat_uptr_t iov_base;
185176 compat_size_t iov_len;
include/linux/msg.h+4−11
@@ -2,6 +2,7 @@ · 1 unmodified line
22 #define _LINUX_MSG_H
33
44 #include <linux/list.h>
5+#include <linux/time64.h>
56 #include <uapi/linux/msg.h>
67
78 /* one msg_msg structure for each message */
@@ -17,9 +18,9 @@ struct msg_msg { · 9 unmodified lines
1718 /* one msq_queue structure for each present queue on the system */
1819 struct msg_queue {
1920 struct kern_ipc_perm q_perm;
20− time_t q_stime; /* last msgsnd time */
21− time_t q_rtime; /* last msgrcv time */
22− time_t q_ctime; /* last change time */
21+ time64_t q_stime; /* last msgsnd time */
22+ time64_t q_rtime; /* last msgrcv time */
23+ time64_t q_ctime; /* last change time */
2324 unsigned long q_cbytes; /* current number of bytes on queue */
2425 unsigned long q_qnum; /* number of messages in queue */
2526 unsigned long q_qbytes; /* max number of bytes on queue */
@@ -31,12 +32,4 @@ struct msg_queue { · 5 unmodified lines
3132 struct list_head q_senders;
3233 } __randomize_layout;
3334
34−/* Helper routines for sys_msgsnd and sys_msgrcv */
35−extern long do_msgsnd(int msqid, long mtype, void __user *mtext,
36− size_t msgsz, int msgflg);
37−extern 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−
4235 #endif /* _LINUX_MSG_H */
include/linux/sem.h+2−1
@@ -4,6 +4,7 @@ · 3 unmodified lines
44 #include <linux/atomic.h>
55 #include <linux/rcupdate.h>
66 #include <linux/cache.h>
7+#include <linux/time64.h>
78 #include <uapi/linux/sem.h>
89
910 struct task_struct;
@@ -30,7 +31,7 @@ struct sem { · 20 unmodified lines
3031 /* One sem_array data structure for each set of semaphores in the system. */
3132 struct sem_array {
3233 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 */
3435 struct list_head pending_alter; /* pending operations */
3536 /* that alter the array */
3637 struct list_head pending_const; /* pending complex operations */
include/linux/shm.h+3−3
@@ -12,9 +12,9 @@ struct shmid_kernel /* private to the kernel */ · 11 unmodified lines
1212 struct file *shm_file;
1313 unsigned long shm_nattch;
1414 unsigned long shm_segsz;
15− time_t shm_atim;
16− time_t shm_dtim;
17− time_t shm_ctim;
15+ time64_t shm_atim;
16+ time64_t shm_dtim;
17+ time64_t shm_ctim;
1818 pid_t shm_cprid;
1919 pid_t shm_lprid;
2020 struct user_struct *mlock_user;
include/linux/time.h+1−1
@@ -178,7 +178,7 @@ extern int do_setitimer(int which, struct itimerval *value, · 177 unmodified lines
178178 struct itimerval *ovalue);
179179 extern int do_getitimer(int which, struct itimerval *value);
180180
181−extern long do_utimes(int dfd, const char __user *filename, struct timespec *times, int flags);
181+extern long do_utimes(int dfd, const char __user *filename, struct timespec64 *times, int flags);
182182
183183 /*
184184 * Similar to the struct tm in userspace <time.h>, but it needs to be here so
init/initramfs.c+1−1
@@ -110,7 +110,7 @@ static void __init free_hash(void) · 109 unmodified lines
110110
111111 static long __init do_utime(char *filename, time_t mtime)
112112 {
113− struct timespec t[2];
113+ struct timespec64 t[2];
114114
115115 t[0].tv_sec = mtime;
116116 t[0].tv_nsec = 0;
ipc/compat.c+32−708
@@ -34,724 +34,48 @@ · 33 unmodified lines
3434
3535 #include "util.h"
3636
37−struct compat_msgbuf {
38− compat_long_t mtype;
39− char mtext[1];
40−};
41−
42−struct 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−
52−struct 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−
63−struct 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−
79−struct 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−
93−struct compat_ipc_kludge {
94− compat_uptr_t msgp;
95− compat_long_t msgtyp;
96−};
97−
98−struct 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−
110−struct 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−
116−static 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−
136−static 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−
147−static 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−
158−static inline int __put_compat_ipc64_perm(struct ipc64_perm *p64,
159− struct compat_ipc64_perm __user *up64)
37+int get_compat_ipc64_perm(struct ipc64_perm *to,
38+ struct compat_ipc64_perm __user *from)
16039 {
161− int err;
162−
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−
173−static 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−
194−static 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−
202−static 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)))
40+ struct compat_ipc64_perm v;
41+ if (copy_from_user(&v, from, sizeof(v)))
20642 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;
20847 }
20948
210−static inline int put_compat_semid64_ds(struct semid64_ds *sem64,
211− struct compat_semid64_ds __user *up64)
49+int get_compat_ipc_perm(struct ipc64_perm *to,
50+ struct compat_ipc_perm __user *from)
21251 {
213− int err;
214−
215− if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64)))
52+ struct compat_ipc_perm v;
53+ if (copy_from_user(&v, from, sizeof(v)))
21654 return -EFAULT;
217− err = __put_compat_ipc64_perm(&sem64->sem_perm, &up64->sem_perm);
218− err |= __put_user(sem64->sem_otime, &up64->sem_otime);
219− err |= __put_user(sem64->sem_ctime, &up64->sem_ctime);
220− err |= __put_user(sem64->sem_nsems, &up64->sem_nsems);
221− return err;
55+ to->uid = v.uid;
56+ to->gid = v.gid;
57+ to->mode = v.mode;
58+ return 0;
22259 }
22360
224−static inline int put_compat_semid_ds(struct semid64_ds *s,
225− struct compat_semid_ds __user *up)
61+void to_compat_ipc64_perm(struct compat_ipc64_perm *to, struct ipc64_perm *from)
22662 {
227− int err;
228−
229− if (!access_ok(VERIFY_WRITE, up, sizeof(*up)))
230− return -EFAULT;
231− err = __put_compat_ipc_perm(&s->sem_perm, &up->sem_perm);
232− err |= __put_user(s->sem_otime, &up->sem_otime);
233− err |= __put_user(s->sem_ctime, &up->sem_ctime);
234− err |= __put_user(s->sem_nsems, &up->sem_nsems);
235− return err;
63+ to->key = from->key;
64+ to->uid = from->uid;
65+ to->gid = from->gid;
66+ to->cuid = from->cuid;
67+ to->cgid = from->cgid;
68+ to->mode = from->mode;
69+ to->seq = from->seq;
23670 }
23771
238−static long do_compat_semctl(int first, int second, int third, u32 pad)
72+void to_compat_ipc_perm(struct compat_ipc_perm *to, struct ipc64_perm *from)
23973 {
240− unsigned long fourth;
241− int err, err2;
242− struct semid64_ds sem64;
243− struct semid64_ds __user *up64;
244− int version = compat_ipc_parse_version(&third);
245−
246− memset(&sem64, 0, sizeof(sem64));
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−
310−static 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
329−COMPAT_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−
413−COMPAT_SYSCALL_DEFINE4(semctl, int, semid, int, semnum, int, cmd, int, arg)
414−{
415− return do_compat_semctl(semid, semnum, cmd, arg);
416−}
417−
418−COMPAT_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−
429−COMPAT_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−
436−static 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−
448−static 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−
460−static 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−
479−static 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−
498−COMPAT_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−
552−COMPAT_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−
564−static 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−
572−static 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−
580−static 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−
598−static 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−
616−static 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−
633−static 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−
650−static 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−
668−COMPAT_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−
749−COMPAT_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);
74+ to->key = from->key;
75+ SET_UID(to->uid, from->uid);
76+ SET_GID(to->gid, from->gid);
77+ SET_UID(to->cuid, from->cuid);
78+ SET_GID(to->cgid, from->cgid);
79+ to->mode = from->mode;
80+ to->seq = from->seq;
75781 }
ipc/mqueue.c+14−14
@@ -668,11 +668,11 @@ static void __do_notify(struct mqueue_inode_info *info) · 667 unmodified lines
668668 }
669669
670670 static int prepare_timeout(const struct timespec __user *u_abs_timeout,
671− struct timespec *ts)
671+ struct timespec64 *ts)
672672 {
673− if (copy_from_user(ts, u_abs_timeout, sizeof(struct timespec)))
673+ if (get_timespec64(ts, u_abs_timeout))
674674 return -EFAULT;
675− if (!timespec_valid(ts))
675+ if (!timespec64_valid(ts))
676676 return -EINVAL;
677677 return 0;
678678 }
@@ -962,7 +962,7 @@ static inline void pipelined_receive(struct wake_q_head *wake_q, · 283 unmodified lines
962962
963963 static int do_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr,
964964 size_t msg_len, unsigned int msg_prio,
965− struct timespec *ts)
965+ struct timespec64 *ts)
966966 {
967967 struct fd f;
968968 struct inode *inode;
@@ -979,7 +979,7 @@ static int do_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr, · 10 unmodified lines
979979 return -EINVAL;
980980
981981 if (ts) {
982− expires = timespec_to_ktime(*ts);
982+ expires = timespec64_to_ktime(*ts);
983983 timeout = &expires;
984984 }
985985
@@ -1080,7 +1080,7 @@ out: · 94 unmodified lines
10801080
10811081 static int do_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr,
10821082 size_t msg_len, unsigned int __user *u_msg_prio,
1083− struct timespec *ts)
1083+ struct timespec64 *ts)
10841084 {
10851085 ssize_t ret;
10861086 struct msg_msg *msg_ptr;
@@ -1092,7 +1092,7 @@ static int do_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr, · 5 unmodified lines
10921092 struct posix_msg_tree_node *new_leaf = NULL;
10931093
10941094 if (ts) {
1095− expires = timespec_to_ktime(*ts);
1095+ expires = timespec64_to_ktime(*ts);
10961096 timeout = &expires;
10971097 }
10981098
@@ -1184,7 +1184,7 @@ SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr, · 85 unmodified lines
11841184 size_t, msg_len, unsigned int, msg_prio,
11851185 const struct timespec __user *, u_abs_timeout)
11861186 {
1187− struct timespec ts, *p = NULL;
1187+ struct timespec64 ts, *p = NULL;
11881188 if (u_abs_timeout) {
11891189 int res = prepare_timeout(u_abs_timeout, &ts);
11901190 if (res)
@@ -1198,7 +1198,7 @@ SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr, · 7 unmodified lines
11981198 size_t, msg_len, unsigned int __user *, u_msg_prio,
11991199 const struct timespec __user *, u_abs_timeout)
12001200 {
1201− struct timespec ts, *p = NULL;
1201+ struct timespec64 ts, *p = NULL;
12021202 if (u_abs_timeout) {
12031203 int res = prepare_timeout(u_abs_timeout, &ts);
12041204 if (res)
@@ -1475,11 +1475,11 @@ COMPAT_SYSCALL_DEFINE4(mq_open, const char __user *, u_name, · 270 unmodified lines
14751475 }
14761476
14771477 static int compat_prepare_timeout(const struct compat_timespec __user *p,
1478− struct timespec *ts)
1478+ struct timespec64 *ts)
14791479 {
1480− if (compat_get_timespec(ts, p))
1480+ if (compat_get_timespec64(ts, p))
14811481 return -EFAULT;
1482− if (!timespec_valid(ts))
1482+ if (!timespec64_valid(ts))
14831483 return -EINVAL;
14841484 return 0;
14851485 }
@@ -1489,7 +1489,7 @@ COMPAT_SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, · 3 unmodified lines
14891489 compat_size_t, msg_len, unsigned int, msg_prio,
14901490 const struct compat_timespec __user *, u_abs_timeout)
14911491 {
1492− struct timespec ts, *p = NULL;
1492+ struct timespec64 ts, *p = NULL;
14931493 if (u_abs_timeout) {
14941494 int res = compat_prepare_timeout(u_abs_timeout, &ts);
14951495 if (res)
@@ -1504,7 +1504,7 @@ COMPAT_SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, · 8 unmodified lines
15041504 compat_size_t, msg_len, unsigned int __user *, u_msg_prio,
15051505 const struct compat_timespec __user *, u_abs_timeout)
15061506 {
1507− struct timespec ts, *p = NULL;
1507+ struct timespec64 ts, *p = NULL;
15081508 if (u_abs_timeout) {
15091509 int res = compat_prepare_timeout(u_abs_timeout, &ts);
15101510 if (res)
ipc/msg.c+255−111
@@ -133,7 +133,7 @@ static int newque(struct ipc_namespace *ns, struct ipc_params *params) · 132 unmodified lines
133133 }
134134
135135 msq->q_stime = msq->q_rtime = 0;
136− msq->q_ctime = get_seconds();
136+ msq->q_ctime = ktime_get_real_seconds();
137137 msq->q_cbytes = msq->q_qnum = 0;
138138 msq->q_qbytes = ns->msg_ctlmnb;
139139 msq->q_lspid = msq->q_lrpid = 0;
@@ -361,23 +361,17 @@ copy_msqid_from_user(struct msqid64_ds *out, void __user *buf, int version) · 221 unmodified lines
361361 * NOTE: no locks must be held, the rwsem is taken inside this function.
362362 */
363363 static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,
364− struct msqid_ds __user *buf, int version)
364+ struct msqid64_ds *msqid64)
365365 {
366366 struct kern_ipc_perm *ipcp;
367− struct msqid64_ds uninitialized_var(msqid64);
368367 struct msg_queue *msq;
369368 int err;
370369
371− if (cmd == IPC_SET) {
372− if (copy_msqid_from_user(&msqid64, buf, version))
373− return -EFAULT;
374− }
375−
376370 down_write(&msg_ids(ns).rwsem);
377371 rcu_read_lock();
378372
379373 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);
381375 if (IS_ERR(ipcp)) {
382376 err = PTR_ERR(ipcp);
383377 goto out_unlock1;
@@ -399,20 +393,20 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd, · 15 unmodified lines
399393 {
400394 DEFINE_WAKE_Q(wake_q);
401395
402− if (msqid64.msg_qbytes > ns->msg_ctlmnb &&
396+ if (msqid64->msg_qbytes > ns->msg_ctlmnb &&
403397 !capable(CAP_SYS_RESOURCE)) {
404398 err = -EPERM;
405399 goto out_unlock1;
406400 }
407401
408402 ipc_lock_object(&msq->q_perm);
409− err = ipc_update_perm(&msqid64.msg_perm, ipcp);
403+ err = ipc_update_perm(&msqid64->msg_perm, ipcp);
410404 if (err)
411405 goto out_unlock0;
412406
413− msq->q_qbytes = msqid64.msg_qbytes;
407+ msq->q_qbytes = msqid64->msg_qbytes;
414408
415− msq->q_ctime = get_seconds();
409+ msq->q_ctime = ktime_get_real_seconds();
416410 /*
417411 * Sleeping receivers might be excluded by
418412 * stricter permissions.
@@ -442,111 +436,89 @@ out_up: · 23 unmodified lines
442436 return err;
443437 }
444438
445−static int msgctl_nolock(struct ipc_namespace *ns, int msqid,
446− int cmd, int version, void __user *buf)
439+static int msgctl_info(struct ipc_namespace *ns, int msqid,
440+ int cmd, struct msginfo *msginfo)
447441 {
448442 int err;
449− struct msg_queue *msq;
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;
443+ int max_id;
469444
470− memset(&msginfo, 0, sizeof(msginfo));
471− msginfo.msgmni = ns->msg_ctlmni;
472− msginfo.msgmax = ns->msg_ctlmax;
473− msginfo.msgmnb = ns->msg_ctlmnb;
474− msginfo.msgssz = MSGSSZ;
475− msginfo.msgseg = MSGSEG;
476− down_read(&msg_ids(ns).rwsem);
477− if (cmd == MSG_INFO) {
478− msginfo.msgpool = msg_ids(ns).in_use;
479− msginfo.msgmap = atomic_read(&ns->msg_hdrs);
480− msginfo.msgtql = atomic_read(&ns->msg_bytes);
481− } else {
482− msginfo.msgmap = MSGMAP;
483− msginfo.msgpool = MSGPOOL;
484− msginfo.msgtql = MSGTQL;
485− }
486− max_id = ipc_get_maxid(&msg_ids(ns));
487− up_read(&msg_ids(ns).rwsem);
488− if (copy_to_user(buf, &msginfo, sizeof(struct msginfo)))
489− return -EFAULT;
490− return (max_id < 0) ? 0 : max_id;
445+ /*
446+ * We must not return kernel stack data.
447+ * due to padding, it's not enough
448+ * to set all member fields.
449+ */
450+ err = security_msg_queue_msgctl(NULL, cmd);
451+ if (err)
452+ return err;
453+
454+ memset(msginfo, 0, sizeof(*msginfo));
455+ msginfo->msgmni = ns->msg_ctlmni;
456+ msginfo->msgmax = ns->msg_ctlmax;
457+ msginfo->msgmnb = ns->msg_ctlmnb;
458+ msginfo->msgssz = MSGSSZ;
459+ msginfo->msgseg = MSGSEG;
460+ down_read(&msg_ids(ns).rwsem);
461+ if (cmd == MSG_INFO) {
462+ msginfo->msgpool = msg_ids(ns).in_use;
463+ msginfo->msgmap = atomic_read(&ns->msg_hdrs);
464+ msginfo->msgtql = atomic_read(&ns->msg_bytes);
465+ } else {
466+ msginfo->msgmap = MSGMAP;
467+ msginfo->msgpool = MSGPOOL;
468+ msginfo->msgtql = MSGTQL;
491469 }
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+}
492474
493− case MSG_STAT:
494− case IPC_STAT:
495− {
496− struct msqid64_ds tbuf;
497− int success_return;
498−
499− if (!buf)
500− return -EFAULT;
501−
502− memset(&tbuf, 0, sizeof(tbuf));
475+static int msgctl_stat(struct ipc_namespace *ns, int msqid,
476+ int cmd, struct msqid64_ds *p)
477+{
478+ int err;
479+ struct msg_queue *msq;
480+ int success_return;
503481
504− rcu_read_lock();
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− }
482+ memset(p, 0, sizeof(*p));
520483
521− err = -EACCES;
522− if (ipcperms(ns, &msq->q_perm, S_IRUGO))
484+ rcu_read_lock();
485+ if (cmd == MSG_STAT) {
486+ msq = msq_obtain_object(ns, msqid);
487+ if (IS_ERR(msq)) {
488+ err = PTR_ERR(msq);
523489 goto out_unlock;
524−
525− err = security_msg_queue_msgctl(msq, cmd);
526− if (err)
490+ }
491+ success_return = msq->q_perm.id;
492+ } else {
493+ msq = msq_obtain_object_check(ns, msqid);
494+ if (IS_ERR(msq)) {
495+ err = PTR_ERR(msq);
527496 goto out_unlock;
497+ }
498+ success_return = 0;
499+ }
528500
529− kernel_to_ipc64_perm(&msq->q_perm, &tbuf.msg_perm);
530− tbuf.msg_stime = msq->q_stime;
531− tbuf.msg_rtime = msq->q_rtime;
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();
501+ err = -EACCES;
502+ if (ipcperms(ns, &msq->q_perm, S_IRUGO))
503+ goto out_unlock;
539504
540− if (copy_msqid_to_user(buf, &tbuf, version))
541− return -EFAULT;
542− return success_return;
543− }
505+ err = security_msg_queue_msgctl(msq, cmd);
506+ if (err)
507+ goto out_unlock;
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();
544519
545− default:
546− return -EINVAL;
547− }
520+ return success_return;
548521
549− return err;
550522 out_unlock:
551523 rcu_read_unlock();
552524 return err;
@@ -556,6 +528,8 @@ SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf) · 3 unmodified lines
556528 {
557529 int version;
558530 struct ipc_namespace *ns;
531+ struct msqid64_ds msqid64;
532+ int err;
559533
560534 if (msqid < 0 || cmd < 0)
561535 return -EINVAL;
@@ -565,18 +539,147 @@ SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf) · 3 unmodified lines
565539
566540 switch (cmd) {
567541 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+ }
569551 case MSG_STAT: /* msqid is an index rather than a msg queue id */
570552 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;
572559 case IPC_SET:
560+ if (copy_msqid_from_user(&msqid64, buf, version))
561+ return -EFAULT;
562+ /* fallthru */
573563 case IPC_RMID:
574− return msgctl_down(ns, msqid, cmd, buf, version);
564+ return msgctl_down(ns, msqid, cmd, &msqid64);
575565 default:
576566 return -EINVAL;
577567 }
578568 }
579569
570+#ifdef CONFIG_COMPAT
571+
572+struct 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+
588+static 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+
608+static 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+
640+COMPAT_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+
580683 static int testmsg(struct msg_msg *msg, long type, int mode)
581684 {
582685 switch (mode) {
@@ -627,7 +730,7 @@ static inline int pipelined_send(struct msg_queue *msq, struct msg_msg *msg, · 44 unmodified lines
627730 return 0;
628731 }
629732
630−long do_msgsnd(int msqid, long mtype, void __user *mtext,
733+static long do_msgsnd(int msqid, long mtype, void __user *mtext,
631734 size_t msgsz, int msgflg)
632735 {
633736 struct msg_queue *msq;
@@ -750,6 +853,25 @@ SYSCALL_DEFINE4(msgsnd, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz, · 116 unmodified lines
750853 return do_msgsnd(msqid, mtype, msgp->mtext, msgsz, msgflg);
751854 }
752855
856+#ifdef CONFIG_COMPAT
857+
858+struct compat_msgbuf {
859+ compat_long_t mtype;
860+ char mtext[1];
861+};
862+
863+COMPAT_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+
753875 static inline int convert_mode(long *msgtyp, int msgflg)
754876 {
755877 if (msgflg & MSG_COPY)
@@ -846,7 +968,7 @@ static struct msg_msg *find_msg(struct msg_queue *msq, long *msgtyp, int mode) · 90 unmodified lines
846968 return found ?: ERR_PTR(-EAGAIN);
847969 }
848970
849−long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, int msgflg,
971+static long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, int msgflg,
850972 long (*msg_handler)(void __user *, struct msg_msg *, size_t))
851973 {
852974 int mode;
@@ -1010,6 +1132,28 @@ SYSCALL_DEFINE5(msgrcv, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz, · 157 unmodified lines
10101132 return do_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg, do_msg_fill);
10111133 }
10121134
1135+#ifdef CONFIG_COMPAT
1136+static 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+
1150+COMPAT_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
10131157
10141158 int msg_init_ns(struct ipc_namespace *ns)
10151159 {
@@ -1039,7 +1183,7 @@ static int sysvipc_msg_proc_show(struct seq_file *s, void *it) · 23 unmodified lines
10391183 struct msg_queue *msq = container_of(ipcp, struct msg_queue, q_perm);
10401184
10411185 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",
10431187 msq->q_perm.key,
10441188 msq->q_perm.id,
10451189 msq->q_perm.mode,
ipc/sem.c+228−116
@@ -512,7 +512,7 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params) · 511 unmodified lines
512512 INIT_LIST_HEAD(&sma->pending_const);
513513 INIT_LIST_HEAD(&sma->list_id);
514514 sma->sem_nsems = nsems;
515− sma->sem_ctime = get_seconds();
515+ sma->sem_ctime = ktime_get_real_seconds();
516516
517517 retval = ipc_addid(&sem_ids(ns), &sma->sem_perm, ns->sc_semmni);
518518 if (retval < 0) {
@@ -1163,14 +1163,14 @@ static unsigned long copy_semid_to_user(void __user *buf, struct semid64_ds *in, · 644 unmodified lines
11631163 }
11641164 }
11651165
1166−static time_t get_semotime(struct sem_array *sma)
1166+static time64_t get_semotime(struct sem_array *sma)
11671167 {
11681168 int i;
1169− time_t res;
1169+ time64_t res;
11701170
11711171 res = sma->sems[0].sem_otime;
11721172 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;
11741174
11751175 if (to > res)
11761176 res = to;
@@ -1178,112 +1178,95 @@ static time_t get_semotime(struct sem_array *sma) · 1 unmodified line
11781178 return res;
11791179 }
11801180
1181−static int semctl_nolock(struct ipc_namespace *ns, int semid,
1182− int cmd, int version, void __user *p)
1181+static int semctl_stat(struct ipc_namespace *ns, int semid,
1182+ int cmd, struct semid64_ds *semid64)
11831183 {
1184− int err;
11851184 struct sem_array *sma;
1185+ int id = 0;
1186+ int err;
11861187
1187− switch (cmd) {
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;
1188+ memset(semid64, 0, sizeof(*semid64));
11971189
1198− memset(&seminfo, 0, sizeof(seminfo));
1199− seminfo.semmni = ns->sc_semmni;
1200− seminfo.semmns = ns->sc_semmns;
1201− seminfo.semmsl = ns->sc_semmsl;
1202− seminfo.semopm = ns->sc_semopm;
1203− seminfo.semvmx = SEMVMX;
1204− seminfo.semmnu = SEMMNU;
1205− seminfo.semmap = SEMMAP;
1206− seminfo.semume = SEMUME;
1207− down_read(&sem_ids(ns).rwsem);
1208− if (cmd == SEM_INFO) {
1209− seminfo.semusz = sem_ids(ns).in_use;
1210− seminfo.semaem = ns->used_sems;
1211− } else {
1212− seminfo.semusz = SEMUSZ;
1213− seminfo.semaem = SEMAEM;
1190+ rcu_read_lock();
1191+ if (cmd == SEM_STAT) {
1192+ sma = sem_obtain_object(ns, semid);
1193+ if (IS_ERR(sma)) {
1194+ err = PTR_ERR(sma);
1195+ goto out_unlock;
1196+ }
1197+ id = sma->sem_perm.id;
1198+ } else {
1199+ sma = sem_obtain_object_check(ns, semid);
1200+ if (IS_ERR(sma)) {
1201+ err = PTR_ERR(sma);
1202+ goto out_unlock;
12141203 }
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;
12201204 }
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));
12281205
1229− rcu_read_lock();
1230− if (cmd == SEM_STAT) {
1231− sma = sem_obtain_object(ns, semid);
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− }
1206+ err = -EACCES;
1207+ if (ipcperms(ns, &sma->sem_perm, S_IRUGO))
1208+ goto out_unlock;
12441209
1245− err = -EACCES;
1246− if (ipcperms(ns, &sma->sem_perm, S_IRUGO))
1247− goto out_unlock;
1210+ err = security_sem_semctl(sma, cmd);
1211+ if (err)
1212+ goto out_unlock;
12481213
1249− err = security_sem_semctl(sma, cmd);
1250− if (err)
1251− goto out_unlock;
1214+ kernel_to_ipc64_perm(&sma->sem_perm, &semid64->sem_perm);
1215+ semid64->sem_otime = get_semotime(sma);
1216+ semid64->sem_ctime = sma->sem_ctime;
1217+ semid64->sem_nsems = sma->sem_nsems;
1218+ rcu_read_unlock();
1219+ return id;
12521220
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− }
12651221 out_unlock:
12661222 rcu_read_unlock();
12671223 return err;
12681224 }
12691225
1226+static 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+
12701261 static int semctl_setval(struct ipc_namespace *ns, int semid, int semnum,
1271− unsigned long arg)
1262+ int val)
12721263 {
12731264 struct sem_undo *un;
12741265 struct sem_array *sma;
12751266 struct sem *curr;
1276− int err, val;
1267+ int err;
12771268 DEFINE_WAKE_Q(wake_q);
12781269
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−
12871270 if (val > SEMVMX || val < 0)
12881271 return -ERANGE;
12891272
@@ -1327,7 +1310,7 @@ static int semctl_setval(struct ipc_namespace *ns, int semid, int semnum, · 37 unmodified lines
13271310
13281311 curr->semval = val;
13291312 curr->sempid = task_tgid_vnr(current);
1330− sma->sem_ctime = get_seconds();
1313+ sma->sem_ctime = ktime_get_real_seconds();
13311314 /* maybe some queued-up processes were waiting for this */
13321315 do_smart_update(sma, NULL, 0, 0, &wake_q);
13331316 sem_unlock(sma, -1);
@@ -1455,7 +1438,7 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum, · 121 unmodified lines
14551438 for (i = 0; i < nsems; i++)
14561439 un->semadj[i] = 0;
14571440 }
1458− sma->sem_ctime = get_seconds();
1441+ sma->sem_ctime = ktime_get_real_seconds();
14591442 /* maybe some queued-up processes were waiting for this */
14601443 do_smart_update(sma, NULL, 0, 0, &wake_q);
14611444 err = 0;
@@ -1532,23 +1515,17 @@ copy_semid_from_user(struct semid64_ds *out, void __user *buf, int version) · 70 unmodified lines
15321515 * NOTE: no locks must be held, the rwsem is taken inside this function.
15331516 */
15341517 static int semctl_down(struct ipc_namespace *ns, int semid,
1535− int cmd, int version, void __user *p)
1518+ int cmd, struct semid64_ds *semid64)
15361519 {
15371520 struct sem_array *sma;
15381521 int err;
1539− struct semid64_ds semid64;
15401522 struct kern_ipc_perm *ipcp;
15411523
1542− if (cmd == IPC_SET) {
1543− if (copy_semid_from_user(&semid64, p, version))
1544− return -EFAULT;
1545− }
1546−
15471524 down_write(&sem_ids(ns).rwsem);
15481525 rcu_read_lock();
15491526
15501527 ipcp = ipcctl_pre_down_nolock(ns, &sem_ids(ns), semid, cmd,
1551− &semid64.sem_perm, 0);
1528+ &semid64->sem_perm, 0);
15521529 if (IS_ERR(ipcp)) {
15531530 err = PTR_ERR(ipcp);
15541531 goto out_unlock1;
@@ -1568,10 +1545,10 @@ static int semctl_down(struct ipc_namespace *ns, int semid, · 13 unmodified lines
15681545 goto out_up;
15691546 case IPC_SET:
15701547 sem_lock(sma, NULL, -1);
1571− err = ipc_update_perm(&semid64.sem_perm, ipcp);
1548+ err = ipc_update_perm(&semid64->sem_perm, ipcp);
15721549 if (err)
15731550 goto out_unlock0;
1574− sma->sem_ctime = get_seconds();
1551+ sma->sem_ctime = ktime_get_real_seconds();
15751552 break;
15761553 default:
15771554 err = -EINVAL;
@@ -1592,6 +1569,8 @@ SYSCALL_DEFINE4(semctl, int, semid, int, semnum, int, cmd, unsigned long, arg) · 14 unmodified lines
15921569 int version;
15931570 struct ipc_namespace *ns;
15941571 void __user *p = (void __user *)arg;
1572+ struct semid64_ds semid64;
1573+ int err;
15951574
15961575 if (semid < 0)
15971576 return -EINVAL;
@@ -1602,25 +1581,136 @@ SYSCALL_DEFINE4(semctl, int, semid, int, semnum, int, cmd, unsigned long, arg) · 4 unmodified lines
16021581 switch (cmd) {
16031582 case IPC_INFO:
16041583 case SEM_INFO:
1584+ return semctl_info(ns, semid, cmd, p);
16051585 case IPC_STAT:
16061586 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;
16081593 case GETALL:
16091594 case GETVAL:
16101595 case GETPID:
16111596 case GETNCNT:
16121597 case GETZCNT:
1598+ case SETALL:
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+
1623+struct 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+
1634+static 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+
1647+static 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+
1669+COMPAT_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:
16131699 case SETALL:
16141700 return semctl_main(ns, semid, semnum, cmd, p);
16151701 case SETVAL:
16161702 return semctl_setval(ns, semid, semnum, arg);
1617− case IPC_RMID:
16181703 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);
16201709 default:
16211710 return -EINVAL;
16221711 }
16231712 }
1713+#endif
16241714
16251715 /* If the task doesn't already have a undo_list, then allocate one
16261716 * here. We guarantee there is only one thread using this undo list,
@@ -1766,8 +1856,8 @@ out: · 139 unmodified lines
17661856 return un;
17671857 }
17681858
1769−SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
1770− unsigned, nsops, const struct timespec __user *, timeout)
1859+static long do_semtimedop(int semid, struct sembuf __user *tsops,
1860+ unsigned nsops, const struct timespec64 *timeout)
17711861 {
17721862 int error = -EINVAL;
17731863 struct sem_array *sma;
@@ -1798,17 +1888,12 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops, · 24 unmodified lines
17981888 }
17991889
18001890 if (timeout) {
1801− struct timespec _timeout;
1802− if (copy_from_user(&_timeout, timeout, sizeof(*timeout))) {
1803− error = -EFAULT;
1804− goto out_free;
1805− }
1806− if (_timeout.tv_sec < 0 || _timeout.tv_nsec < 0 ||
1807− _timeout.tv_nsec >= 1000000000L) {
1891+ if (timeout->tv_sec < 0 || timeout->tv_nsec < 0 ||
1892+ timeout->tv_nsec >= 1000000000L) {
18081893 error = -EINVAL;
18091894 goto out_free;
18101895 }
1811− jiffies_left = timespec_to_jiffies(&_timeout);
1896+ jiffies_left = timespec64_to_jiffies(timeout);
18121897 }
18131898
18141899 max = 0;
@@ -2023,10 +2108,37 @@ out_free: · 208 unmodified lines
20232108 return error;
20242109 }
20252110
2111+SYSCALL_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
2124+COMPAT_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+
20262138 SYSCALL_DEFINE3(semop, int, semid, struct sembuf __user *, tsops,
20272139 unsigned, nsops)
20282140 {
2029− return sys_semtimedop(semid, tsops, nsops, NULL);
2141+ return do_semtimedop(semid, tsops, nsops, NULL);
20302142 }
20312143
20322144 /* 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) · 150 unmodified lines
21832295 struct user_namespace *user_ns = seq_user_ns(s);
21842296 struct kern_ipc_perm *ipcp = it;
21852297 struct sem_array *sma = container_of(ipcp, struct sem_array, sem_perm);
2186− time_t sem_otime;
2298+ time64_t sem_otime;
21872299
21882300 /*
21892301 * 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) · 6 unmodified lines
21962308 sem_otime = get_semotime(sma);
21972309
21982310 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",
22002312 sma->sem_perm.key,
22012313 sma->sem_perm.id,
22022314 sma->sem_perm.mode,
ipc/shm.c+363−170
@@ -202,7 +202,7 @@ static int __shm_open(struct vm_area_struct *vma) · 201 unmodified lines
202202 if (IS_ERR(shp))
203203 return PTR_ERR(shp);
204204
205− shp->shm_atim = get_seconds();
205+ shp->shm_atim = ktime_get_real_seconds();
206206 shp->shm_lprid = task_tgid_vnr(current);
207207 shp->shm_nattch++;
208208 shm_unlock(shp);
@@ -289,7 +289,7 @@ static void shm_close(struct vm_area_struct *vma) · 80 unmodified lines
289289 goto done; /* no-op */
290290
291291 shp->shm_lprid = task_tgid_vnr(current);
292− shp->shm_dtim = get_seconds();
292+ shp->shm_dtim = ktime_get_real_seconds();
293293 shp->shm_nattch--;
294294 if (shm_may_destroy(ns, shp))
295295 shm_destroy(ns, shp);
@@ -594,7 +594,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params) · 298 unmodified lines
594594 shp->shm_cprid = task_tgid_vnr(current);
595595 shp->shm_lprid = 0;
596596 shp->shm_atim = shp->shm_dtim = 0;
597− shp->shm_ctim = get_seconds();
597+ shp->shm_ctim = ktime_get_real_seconds();
598598 shp->shm_segsz = size;
599599 shp->shm_nattch = 0;
600600 shp->shm_file = file;
@@ -815,23 +815,17 @@ static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss, · 214 unmodified lines
815815 * NOTE: no locks must be held, the rwsem is taken inside this function.
816816 */
817817 static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd,
818− struct shmid_ds __user *buf, int version)
818+ struct shmid64_ds *shmid64)
819819 {
820820 struct kern_ipc_perm *ipcp;
821− struct shmid64_ds shmid64;
822821 struct shmid_kernel *shp;
823822 int err;
824823
825− if (cmd == IPC_SET) {
826− if (copy_shmid_from_user(&shmid64, buf, version))
827− return -EFAULT;
828− }
829−
830824 down_write(&shm_ids(ns).rwsem);
831825 rcu_read_lock();
832826
833827 ipcp = ipcctl_pre_down_nolock(ns, &shm_ids(ns), shmid, cmd,
834− &shmid64.shm_perm, 0);
828+ &shmid64->shm_perm, 0);
835829 if (IS_ERR(ipcp)) {
836830 err = PTR_ERR(ipcp);
837831 goto out_unlock1;
@@ -851,10 +845,10 @@ static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd, · 13 unmodified lines
851845 goto out_up;
852846 case IPC_SET:
853847 ipc_lock_object(&shp->shm_perm);
854− err = ipc_update_perm(&shmid64.shm_perm, ipcp);
848+ err = ipc_update_perm(&shmid64->shm_perm, ipcp);
855849 if (err)
856850 goto out_unlock0;
857− shp->shm_ctim = get_seconds();
851+ shp->shm_ctim = ktime_get_real_seconds();
858852 break;
859853 default:
860854 err = -EINVAL;
@@ -870,125 +864,175 @@ out_up: · 9 unmodified lines
870864 return err;
871865 }
872866
873−static int shmctl_nolock(struct ipc_namespace *ns, int shmid,
874− int cmd, int version, void __user *buf)
867+static int shmctl_ipc_info(struct ipc_namespace *ns,
868+ struct shminfo64 *shminfo)
875869 {
876− int err;
877− struct shmid_kernel *shp;
878−
879− /* preliminary security checks for *_INFO */
880− if (cmd == IPC_INFO || cmd == SHM_INFO) {
881− err = security_shm_shmctl(NULL, cmd);
882− if (err)
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−
870+ int err = security_shm_shmctl(NULL, IPC_INFO);
871+ if (!err) {
872+ memset(shminfo, 0, sizeof(*shminfo));
873+ shminfo->shmmni = shminfo->shmseg = ns->shm_ctlmni;
874+ shminfo->shmmax = ns->shm_ctlmax;
875+ shminfo->shmall = ns->shm_ctlall;
876+ shminfo->shmmin = SHMMIN;
900877 down_read(&shm_ids(ns).rwsem);
901878 err = ipc_get_maxid(&shm_ids(ns));
902879 up_read(&shm_ids(ns).rwsem);
903−
904880 if (err < 0)
905881 err = 0;
906− goto out;
907882 }
908− case SHM_INFO:
909− {
910− struct shm_info shm_info;
883+ return err;
884+}
911885
912− memset(&shm_info, 0, sizeof(shm_info));
886+static 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));
913892 down_read(&shm_ids(ns).rwsem);
914− shm_info.used_ids = shm_ids(ns).in_use;
915− shm_get_stat(ns, &shm_info.shm_rss, &shm_info.shm_swp);
916− shm_info.shm_tot = ns->shm_tot;
917− shm_info.swap_attempts = 0;
918− shm_info.swap_successes = 0;
893+ shm_info->used_ids = shm_ids(ns).in_use;
894+ shm_get_stat(ns, &shm_info->shm_rss, &shm_info->shm_swp);
895+ shm_info->shm_tot = ns->shm_tot;
896+ shm_info->swap_attempts = 0;
897+ shm_info->swap_successes = 0;
919898 err = ipc_get_maxid(&shm_ids(ns));
920899 up_read(&shm_ids(ns).rwsem);
921− if (copy_to_user(buf, &shm_info, sizeof(shm_info))) {
922− err = -EFAULT;
923− goto out;
900+ if (err < 0)
901+ err = 0;
902+ }
903+ return err;
904+}
905+
906+static 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;
924926 }
927+ result = 0;
928+ }
925929
926− err = err < 0 ? 0 : err;
927− goto out;
930+ err = -EACCES;
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+
950+out_unlock:
951+ rcu_read_unlock();
952+ return err;
953+}
954+
955+static 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;
928966 }
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− }
951967
952− err = -EACCES;
953− if (ipcperms(ns, &shp->shm_perm, S_IRUGO))
954− goto out_unlock;
968+ audit_ipc_obj(&(shp->shm_perm));
969+ err = security_shm_shmctl(shp, cmd);
970+ if (err)
971+ goto out_unlock1;
955972
956− err = security_shm_shmctl(shp, cmd);
957− if (err)
958− goto out_unlock;
973+ ipc_lock_object(&shp->shm_perm);
959974
960− memset(&tbuf, 0, sizeof(tbuf));
961− kernel_to_ipc64_perm(&shp->shm_perm, &tbuf.shm_perm);
962− tbuf.shm_segsz = shp->shm_segsz;
963− tbuf.shm_atime = shp->shm_atim;
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;
975+ /* check if shm_destroy() is tearing down shp */
976+ if (!ipc_valid_object(&shp->shm_perm)) {
977+ err = -EIDRM;
978+ goto out_unlock0;
976979 }
977− default:
978− return -EINVAL;
980+
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+ }
979993 }
980994
981−out_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+
1024+out_unlock0:
1025+ ipc_unlock_object(&shp->shm_perm);
1026+out_unlock1:
9821027 rcu_read_unlock();
983−out:
9841028 return err;
9851029 }
9861030
9871031 SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
9881032 {
989− struct shmid_kernel *shp;
9901033 int err, version;
9911034 struct ipc_namespace *ns;
1035+ struct shmid64_ds sem64;
9921036
9931037 if (cmd < 0 || shmid < 0)
9941038 return -EINVAL;
@@ -997,92 +1041,222 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf) · 2 unmodified lines
9971041 ns = current->nsproxy->ipc_ns;
9981042
9991043 switch (cmd) {
1000− case IPC_INFO:
1001− case SHM_INFO:
1044+ case IPC_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+ }
10021062 case SHM_STAT:
1003− case IPC_STAT:
1004− return shmctl_nolock(ns, shmid, cmd, version, buf);
1005− case IPC_RMID:
1063+ case IPC_STAT: {
1064+ err = shmctl_stat(ns, shmid, cmd, &sem64);
1065+ if (err < 0)
1066+ return err;
1067+ if (copy_shmid_to_user(buf, &sem64, version))
1068+ err = -EFAULT;
1069+ return err;
1070+ }
10061071 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);
10081077 case SHM_LOCK:
10091078 case SHM_UNLOCK:
1010− {
1011− struct file *shm_file;
1079+ return shmctl_do_lock(ns, shmid, cmd);
1080+ default:
1081+ return -EINVAL;
1082+ }
1083+}
10121084
1013− rcu_read_lock();
1014− shp = shm_obtain_object_check(ns, shmid);
1015− if (IS_ERR(shp)) {
1016− err = PTR_ERR(shp);
1017− goto out_unlock1;
1018− }
1085+#ifdef CONFIG_COMPAT
1086+
1087+struct compat_shmid_ds {
1088+ struct compat_ipc_perm shm_perm;
1089+ int shm_segsz;
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+};
10191100
1020− audit_ipc_obj(&(shp->shm_perm));
1021− err = security_shm_shmctl(shp, cmd);
1022− if (err)
1023− goto out_unlock1;
1101+struct compat_shminfo64 {
1102+ compat_ulong_t shmmax;
1103+ compat_ulong_t shmmin;
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+};
10241112
1025− ipc_lock_object(&shp->shm_perm);
1113+struct 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+};
10261118
1027− /* check if shm_destroy() is tearing down shp */
1028− if (!ipc_valid_object(&shp->shm_perm)) {
1029− err = -EIDRM;
1030− goto out_unlock0;
1031− }
1119+static int copy_compat_shminfo_to_user(void __user *buf, struct shminfo64 *in,
1120+ int version)
1121+{
1122+ if (in->shmmax > INT_MAX)
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+}
10321144
1033− if (!ns_capable(ns->user_ns, CAP_IPC_LOCK)) {
1034− kuid_t euid = current_euid();
1035−
1036− if (!uid_eq(euid, shp->shm_perm.uid) &&
1037− !uid_eq(euid, shp->shm_perm.cuid)) {
1038− err = -EPERM;
1039− goto out_unlock0;
1040− }
1041− if (cmd == SHM_LOCK && !rlimit(RLIMIT_MEMLOCK)) {
1042− err = -EPERM;
1043− goto out_unlock0;
1044− }
1045− }
1145+static int put_compat_shm_info(struct shm_info *ip,
1146+ struct compat_shm_info __user *uip)
1147+{
1148+ struct compat_shm_info info;
1149+
1150+ memset(&info, 0, sizeof(info));
1151+ info.used_ids = ip->used_ids;
1152+ info.shm_tot = ip->shm_tot;
1153+ info.shm_rss = ip->shm_rss;
1154+ info.shm_swp = ip->shm_swp;
1155+ info.swap_attempts = ip->swap_attempts;
1156+ info.swap_successes = ip->swap_successes;
1157+ return copy_to_user(up, &info, sizeof(info));
1158+}
10461159
1047− shm_file = shp->shm_file;
1048− if (is_file_hugepages(shm_file))
1049− goto out_unlock0;
1160+static int copy_compat_shmid_to_user(void __user *buf, struct shmid64_ds *in,
1161+ int version)
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+}
10501190
1051− if (cmd == SHM_LOCK) {
1052− struct user_struct *user = current_user();
1191+static int copy_compat_shmid_from_user(struct shmid64_ds *out, void __user *buf,
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+}
10531203
1054− err = shmem_lock(shm_file, 1, user);
1055− if (!err && !(shp->shm_perm.mode & SHM_LOCKED)) {
1056− shp->shm_perm.mode |= SHM_LOCKED;
1057− shp->mlock_user = user;
1058− }
1059− goto out_unlock0;
1060− }
1204+COMPAT_SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, void __user *, uptr)
1205+{
1206+ struct ipc_namespace *ns;
1207+ struct shmid64_ds sem64;
1208+ int version = compat_ipc_parse_version(&cmd);
1209+ int err;
10611210
1062− /* SHM_UNLOCK */
1063− if (!(shp->shm_perm.mode & SHM_LOCKED))
1064− goto out_unlock0;
1065− shmem_lock(shm_file, 0, shp->mlock_user);
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);
1211+ ns = current->nsproxy->ipc_ns;
1212+
1213+ if (cmd < 0 || shmid < 0)
1214+ return -EINVAL;
10721215
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;
10741233 return err;
10751234 }
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;
10761254 default:
10771255 return -EINVAL;
10781256 }
1079−
1080−out_unlock0:
1081− ipc_unlock_object(&shp->shm_perm);
1082−out_unlock1:
1083− rcu_read_unlock();
10841257 return err;
10851258 }
1259+#endif
10861260
10871261 /*
10881262 * 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) · 178 unmodified lines
12671441 return (long)ret;
12681442 }
12691443
1444+#ifdef CONFIG_COMPAT
1445+
1446+#ifndef COMPAT_SHMLBA
1447+#define COMPAT_SHMLBA SHMLBA
1448+#endif
1449+
1450+COMPAT_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+
12701463 /*
12711464 * detach and kill segment if marked destroyed.
12721465 * The work is done in shm_close.
@@ -1397,7 +1590,7 @@ static int sysvipc_shm_proc_show(struct seq_file *s, void *it) · 124 unmodified lines
13971590
13981591 seq_printf(s,
13991592 "%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 "
14011594 SIZE_SPEC " " SIZE_SPEC "\n",
14021595 shp->shm_perm.key,
14031596 shp->shm_perm.id,
ipc/syscall.c+89−1
@@ -5,12 +5,12 @@ · 4 unmodified lines
55 * the individual syscalls instead.
66 */
77 #include <linux/unistd.h>
8+#include <linux/syscalls.h>
89
910 #ifdef __ARCH_WANT_SYS_IPC
1011 #include <linux/errno.h>
1112 #include <linux/ipc.h>
1213 #include <linux/shm.h>
13−#include <linux/syscalls.h>
1414 #include <linux/uaccess.h>
1515
1616 SYSCALL_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, · 80 unmodified lines
9797 }
9898 }
9999 #endif
100+
101+#ifdef CONFIG_COMPAT
102+#include <linux/compat.h>
103+
104+#ifndef COMPAT_SHMLBA
105+#define COMPAT_SHMLBA SHMLBA
106+#endif
107+
108+struct compat_ipc_kludge {
109+ compat_uptr_t msgp;
110+ compat_long_t msgtyp;
111+};
112+
113+#ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC
114+COMPAT_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
ipc/util.h+30−0
@@ -194,4 +194,34 @@ int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids, · 193 unmodified lines
194194 const struct ipc_ops *ops, struct ipc_params *params);
195195 void free_ipcs(struct ipc_namespace *ns, struct ipc_ids *ids,
196196 void (*free)(struct ipc_namespace *, struct kern_ipc_perm *));
197+
198+#ifdef CONFIG_COMPAT
199+#include <linux/compat.h>
200+struct 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+
210+void to_compat_ipc_perm(struct compat_ipc_perm *, struct ipc64_perm *);
211+void to_compat_ipc64_perm(struct compat_ipc64_perm *, struct ipc64_perm *);
212+int get_compat_ipc_perm(struct ipc64_perm *, struct compat_ipc_perm __user *);
213+int get_compat_ipc64_perm(struct ipc64_perm *,
214+ struct compat_ipc64_perm __user *);
215+
216+static 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
197227 #endif
kernel/audit.h+1−1
@@ -182,7 +182,7 @@ struct audit_context { · 181 unmodified lines
182182 mqd_t mqdes;
183183 size_t msg_len;
184184 unsigned int msg_prio;
185− struct timespec abs_timeout;
185+ struct timespec64 abs_timeout;
186186 } mq_sendrecv;
187187 struct {
188188 int oflag;
kernel/auditsc.c+6−6
@@ -1235,11 +1235,11 @@ static void show_special(struct audit_context *context, int *call_panic) · 1234 unmodified lines
12351235 case AUDIT_MQ_SENDRECV:
12361236 audit_log_format(ab,
12371237 "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",
12391239 context->mq_sendrecv.mqdes,
12401240 context->mq_sendrecv.msg_len,
12411241 context->mq_sendrecv.msg_prio,
1242− context->mq_sendrecv.abs_timeout.tv_sec,
1242+ (long long) context->mq_sendrecv.abs_timeout.tv_sec,
12431243 context->mq_sendrecv.abs_timeout.tv_nsec);
12441244 break;
12451245 case AUDIT_MQ_NOTIFY:
@@ -2083,15 +2083,15 @@ void __audit_mq_open(int oflag, umode_t mode, struct mq_attr *attr) · 837 unmodified lines
20832083 *
20842084 */
20852085 void __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)
20872087 {
20882088 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;
20902090
20912091 if (abs_timeout)
2092− memcpy(p, abs_timeout, sizeof(struct timespec));
2092+ memcpy(p, abs_timeout, sizeof(*p));
20932093 else
2094− memset(p, 0, sizeof(struct timespec));
2094+ memset(p, 0, sizeof(*p));
20952095
20962096 context->mq_sendrecv.mqdes = mqdes;
20972097 context->mq_sendrecv.msg_len = msg_len;
kernel/compat.c+0−23
@@ -200,29 +200,6 @@ int compat_put_timespec(const struct timespec *ts, void __user *uts) · 199 unmodified lines
200200 }
201201 EXPORT_SYMBOL_GPL(compat_put_timespec);
202202
203−int 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−
226203 int get_compat_itimerval(struct itimerval *o, const struct compat_itimerval __user *i)
227204 {
228205 struct compat_itimerval v32;