Commit cc73fee0 authored by Linus Torvalds's avatar Linus Torvalds

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
parents e7cdb60f aaed2dd8
...@@ -56,9 +56,4 @@ config IA64_DEBUG_IRQ ...@@ -56,9 +56,4 @@ config IA64_DEBUG_IRQ
and restore instructions. It's useful for tracking down spinlock and restore instructions. It's useful for tracking down spinlock
problems, but slow! If you're unsure, select N. problems, but slow! If you're unsure, select N.
config SYSVIPC_COMPAT
bool
depends on COMPAT && SYSVIPC
default y
endmenu endmenu
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
*/ */
SYSCALL_DEFINE2(utime, char __user *, filename, struct utimbuf __user *, times) SYSCALL_DEFINE2(utime, char __user *, filename, struct utimbuf __user *, times)
{ {
struct timespec tv[2]; struct timespec64 tv[2];
if (times) { if (times) {
if (get_user(tv[0].tv_sec, &times->actime) || if (get_user(tv[0].tv_sec, &times->actime) ||
...@@ -44,7 +44,7 @@ static bool nsec_valid(long nsec) ...@@ -44,7 +44,7 @@ static bool nsec_valid(long nsec)
return nsec >= 0 && nsec <= 999999999; return nsec >= 0 && nsec <= 999999999;
} }
static int utimes_common(const struct path *path, struct timespec *times) static int utimes_common(const struct path *path, struct timespec64 *times)
{ {
int error; int error;
struct iattr newattrs; struct iattr newattrs;
...@@ -115,7 +115,7 @@ static int utimes_common(const struct path *path, struct timespec *times) ...@@ -115,7 +115,7 @@ static int utimes_common(const struct path *path, struct timespec *times)
* must be owner or have write permission. * must be owner or have write permission.
* Else, update from *times, must be owner or super user. * Else, update from *times, must be owner or super user.
*/ */
long do_utimes(int dfd, const char __user *filename, struct timespec *times, long do_utimes(int dfd, const char __user *filename, struct timespec64 *times,
int flags) int flags)
{ {
int error = -EINVAL; int error = -EINVAL;
...@@ -167,10 +167,11 @@ long do_utimes(int dfd, const char __user *filename, struct timespec *times, ...@@ -167,10 +167,11 @@ long do_utimes(int dfd, const char __user *filename, struct timespec *times,
SYSCALL_DEFINE4(utimensat, int, dfd, const char __user *, filename, SYSCALL_DEFINE4(utimensat, int, dfd, const char __user *, filename,
struct timespec __user *, utimes, int, flags) struct timespec __user *, utimes, int, flags)
{ {
struct timespec tstimes[2]; struct timespec64 tstimes[2];
if (utimes) { if (utimes) {
if (copy_from_user(&tstimes, utimes, sizeof(tstimes))) if ((get_timespec64(&tstimes[0], &utimes[0]) ||
get_timespec64(&tstimes[1], &utimes[1])))
return -EFAULT; return -EFAULT;
/* Nothing to do, we must not even check the path. */ /* Nothing to do, we must not even check the path. */
...@@ -186,7 +187,7 @@ SYSCALL_DEFINE3(futimesat, int, dfd, const char __user *, filename, ...@@ -186,7 +187,7 @@ SYSCALL_DEFINE3(futimesat, int, dfd, const char __user *, filename,
struct timeval __user *, utimes) struct timeval __user *, utimes)
{ {
struct timeval times[2]; struct timeval times[2];
struct timespec tstimes[2]; struct timespec64 tstimes[2];
if (utimes) { if (utimes) {
if (copy_from_user(&times, utimes, sizeof(times))) if (copy_from_user(&times, utimes, sizeof(times)))
...@@ -224,7 +225,7 @@ SYSCALL_DEFINE2(utimes, char __user *, filename, ...@@ -224,7 +225,7 @@ SYSCALL_DEFINE2(utimes, char __user *, filename,
COMPAT_SYSCALL_DEFINE2(utime, const char __user *, filename, COMPAT_SYSCALL_DEFINE2(utime, const char __user *, filename,
struct compat_utimbuf __user *, t) struct compat_utimbuf __user *, t)
{ {
struct timespec tv[2]; struct timespec64 tv[2];
if (t) { if (t) {
if (get_user(tv[0].tv_sec, &t->actime) || if (get_user(tv[0].tv_sec, &t->actime) ||
...@@ -238,11 +239,11 @@ COMPAT_SYSCALL_DEFINE2(utime, const char __user *, filename, ...@@ -238,11 +239,11 @@ COMPAT_SYSCALL_DEFINE2(utime, const char __user *, filename,
COMPAT_SYSCALL_DEFINE4(utimensat, unsigned int, dfd, const char __user *, filename, struct compat_timespec __user *, t, int, flags) COMPAT_SYSCALL_DEFINE4(utimensat, unsigned int, dfd, const char __user *, filename, struct compat_timespec __user *, t, int, flags)
{ {
struct timespec tv[2]; struct timespec64 tv[2];
if (t) { if (t) {
if (compat_get_timespec(&tv[0], &t[0]) || if (compat_get_timespec64(&tv[0], &t[0]) ||
compat_get_timespec(&tv[1], &t[1])) compat_get_timespec64(&tv[1], &t[1]))
return -EFAULT; return -EFAULT;
if (tv[0].tv_nsec == UTIME_OMIT && tv[1].tv_nsec == UTIME_OMIT) if (tv[0].tv_nsec == UTIME_OMIT && tv[1].tv_nsec == UTIME_OMIT)
...@@ -253,7 +254,7 @@ COMPAT_SYSCALL_DEFINE4(utimensat, unsigned int, dfd, const char __user *, filena ...@@ -253,7 +254,7 @@ COMPAT_SYSCALL_DEFINE4(utimensat, unsigned int, dfd, const char __user *, filena
COMPAT_SYSCALL_DEFINE3(futimesat, unsigned int, dfd, const char __user *, filename, struct compat_timeval __user *, t) COMPAT_SYSCALL_DEFINE3(futimesat, unsigned int, dfd, const char __user *, filename, struct compat_timeval __user *, t)
{ {
struct timespec tv[2]; struct timespec64 tv[2];
if (t) { if (t) {
if (get_user(tv[0].tv_sec, &t[0].tv_sec) || if (get_user(tv[0].tv_sec, &t[0].tv_sec) ||
......
...@@ -351,7 +351,7 @@ extern int __audit_socketcall(int nargs, unsigned long *args); ...@@ -351,7 +351,7 @@ extern int __audit_socketcall(int nargs, unsigned long *args);
extern int __audit_sockaddr(int len, void *addr); extern int __audit_sockaddr(int len, void *addr);
extern void __audit_fd_pair(int fd1, int fd2); extern void __audit_fd_pair(int fd1, int fd2);
extern void __audit_mq_open(int oflag, umode_t mode, struct mq_attr *attr); extern void __audit_mq_open(int oflag, umode_t mode, struct mq_attr *attr);
extern void __audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec *abs_timeout); extern void __audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec64 *abs_timeout);
extern void __audit_mq_notify(mqd_t mqdes, const struct sigevent *notification); extern void __audit_mq_notify(mqd_t mqdes, const struct sigevent *notification);
extern void __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat); extern void __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat);
extern int __audit_log_bprm_fcaps(struct linux_binprm *bprm, 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) ...@@ -412,7 +412,7 @@ static inline void audit_mq_open(int oflag, umode_t mode, struct mq_attr *attr)
if (unlikely(!audit_dummy_context())) if (unlikely(!audit_dummy_context()))
__audit_mq_open(oflag, mode, attr); __audit_mq_open(oflag, mode, attr);
} }
static inline void audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec *abs_timeout) static inline void audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec64 *abs_timeout)
{ {
if (unlikely(!audit_dummy_context())) if (unlikely(!audit_dummy_context()))
__audit_mq_sendrecv(mqdes, msg_len, msg_prio, abs_timeout); __audit_mq_sendrecv(mqdes, msg_len, msg_prio, abs_timeout);
...@@ -549,7 +549,7 @@ static inline void audit_mq_open(int oflag, umode_t mode, struct mq_attr *attr) ...@@ -549,7 +549,7 @@ static inline void audit_mq_open(int oflag, umode_t mode, struct mq_attr *attr)
{ } { }
static inline void audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, static inline void audit_mq_sendrecv(mqd_t mqdes, size_t msg_len,
unsigned int msg_prio, unsigned int msg_prio,
const struct timespec *abs_timeout) const struct timespec64 *abs_timeout)
{ } { }
static inline void audit_mq_notify(mqd_t mqdes, static inline void audit_mq_notify(mqd_t mqdes,
const struct sigevent *notification) const struct sigevent *notification)
......
...@@ -171,15 +171,6 @@ extern int get_compat_itimerspec64(struct itimerspec64 *its, ...@@ -171,15 +171,6 @@ extern int get_compat_itimerspec64(struct itimerspec64 *its,
extern int put_compat_itimerspec64(const struct itimerspec64 *its, extern int put_compat_itimerspec64(const struct itimerspec64 *its,
struct compat_itimerspec __user *uits); struct compat_itimerspec __user *uits);
/*
* This function convert a timespec if necessary and returns a *user
* space* pointer. If no conversion is necessary, it returns the
* initial pointer. NULL is a legitimate argument and will always
* output NULL.
*/
extern int compat_convert_timespec(struct timespec __user **,
const void __user *);
struct compat_iovec { struct compat_iovec {
compat_uptr_t iov_base; compat_uptr_t iov_base;
compat_size_t iov_len; compat_size_t iov_len;
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#define _LINUX_MSG_H #define _LINUX_MSG_H
#include <linux/list.h> #include <linux/list.h>
#include <linux/time64.h>
#include <uapi/linux/msg.h> #include <uapi/linux/msg.h>
/* one msg_msg structure for each message */ /* one msg_msg structure for each message */
...@@ -17,9 +18,9 @@ struct msg_msg { ...@@ -17,9 +18,9 @@ struct msg_msg {
/* one msq_queue structure for each present queue on the system */ /* one msq_queue structure for each present queue on the system */
struct msg_queue { struct msg_queue {
struct kern_ipc_perm q_perm; struct kern_ipc_perm q_perm;
time_t q_stime; /* last msgsnd time */ time64_t q_stime; /* last msgsnd time */
time_t q_rtime; /* last msgrcv time */ time64_t q_rtime; /* last msgrcv time */
time_t q_ctime; /* last change time */ time64_t q_ctime; /* last change time */
unsigned long q_cbytes; /* current number of bytes on queue */ unsigned long q_cbytes; /* current number of bytes on queue */
unsigned long q_qnum; /* number of messages in queue */ unsigned long q_qnum; /* number of messages in queue */
unsigned long q_qbytes; /* max number of bytes on queue */ unsigned long q_qbytes; /* max number of bytes on queue */
...@@ -31,12 +32,4 @@ struct msg_queue { ...@@ -31,12 +32,4 @@ struct msg_queue {
struct list_head q_senders; struct list_head q_senders;
} __randomize_layout; } __randomize_layout;
/* Helper routines for sys_msgsnd and sys_msgrcv */
extern long do_msgsnd(int msqid, long mtype, void __user *mtext,
size_t msgsz, int msgflg);
extern long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
int msgflg,
long (*msg_fill)(void __user *, struct msg_msg *,
size_t));
#endif /* _LINUX_MSG_H */ #endif /* _LINUX_MSG_H */
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include <linux/atomic.h> #include <linux/atomic.h>
#include <linux/rcupdate.h> #include <linux/rcupdate.h>
#include <linux/cache.h> #include <linux/cache.h>
#include <linux/time64.h>
#include <uapi/linux/sem.h> #include <uapi/linux/sem.h>
struct task_struct; struct task_struct;
...@@ -30,7 +31,7 @@ struct sem { ...@@ -30,7 +31,7 @@ struct sem {
/* One sem_array data structure for each set of semaphores in the system. */ /* One sem_array data structure for each set of semaphores in the system. */
struct sem_array { struct sem_array {
struct kern_ipc_perm sem_perm; /* permissions .. see ipc.h */ struct kern_ipc_perm sem_perm; /* permissions .. see ipc.h */
time_t sem_ctime; /* create/last semctl() time */ time64_t sem_ctime; /* create/last semctl() time */
struct list_head pending_alter; /* pending operations */ struct list_head pending_alter; /* pending operations */
/* that alter the array */ /* that alter the array */
struct list_head pending_const; /* pending complex operations */ struct list_head pending_const; /* pending complex operations */
......
...@@ -12,9 +12,9 @@ struct shmid_kernel /* private to the kernel */ ...@@ -12,9 +12,9 @@ struct shmid_kernel /* private to the kernel */
struct file *shm_file; struct file *shm_file;
unsigned long shm_nattch; unsigned long shm_nattch;
unsigned long shm_segsz; unsigned long shm_segsz;
time_t shm_atim; time64_t shm_atim;
time_t shm_dtim; time64_t shm_dtim;
time_t shm_ctim; time64_t shm_ctim;
pid_t shm_cprid; pid_t shm_cprid;
pid_t shm_lprid; pid_t shm_lprid;
struct user_struct *mlock_user; struct user_struct *mlock_user;
......
...@@ -178,7 +178,7 @@ extern int do_setitimer(int which, struct itimerval *value, ...@@ -178,7 +178,7 @@ extern int do_setitimer(int which, struct itimerval *value,
struct itimerval *ovalue); struct itimerval *ovalue);
extern int do_getitimer(int which, struct itimerval *value); extern int do_getitimer(int which, struct itimerval *value);
extern long do_utimes(int dfd, const char __user *filename, struct timespec *times, int flags); extern long do_utimes(int dfd, const char __user *filename, struct timespec64 *times, int flags);
/* /*
* Similar to the struct tm in userspace <time.h>, but it needs to be here so * Similar to the struct tm in userspace <time.h>, but it needs to be here so
......
...@@ -110,7 +110,7 @@ static void __init free_hash(void) ...@@ -110,7 +110,7 @@ static void __init free_hash(void)
static long __init do_utime(char *filename, time_t mtime) static long __init do_utime(char *filename, time_t mtime)
{ {
struct timespec t[2]; struct timespec64 t[2];
t[0].tv_sec = mtime; t[0].tv_sec = mtime;
t[0].tv_nsec = 0; t[0].tv_nsec = 0;
......
This diff is collapsed.
...@@ -668,11 +668,11 @@ static void __do_notify(struct mqueue_inode_info *info) ...@@ -668,11 +668,11 @@ static void __do_notify(struct mqueue_inode_info *info)
} }
static int prepare_timeout(const struct timespec __user *u_abs_timeout, static int prepare_timeout(const struct timespec __user *u_abs_timeout,
struct timespec *ts) struct timespec64 *ts)
{ {
if (copy_from_user(ts, u_abs_timeout, sizeof(struct timespec))) if (get_timespec64(ts, u_abs_timeout))
return -EFAULT; return -EFAULT;
if (!timespec_valid(ts)) if (!timespec64_valid(ts))
return -EINVAL; return -EINVAL;
return 0; return 0;
} }
...@@ -962,7 +962,7 @@ static inline void pipelined_receive(struct wake_q_head *wake_q, ...@@ -962,7 +962,7 @@ static inline void pipelined_receive(struct wake_q_head *wake_q,
static int do_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr, static int do_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr,
size_t msg_len, unsigned int msg_prio, size_t msg_len, unsigned int msg_prio,
struct timespec *ts) struct timespec64 *ts)
{ {
struct fd f; struct fd f;
struct inode *inode; struct inode *inode;
...@@ -979,7 +979,7 @@ static int do_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr, ...@@ -979,7 +979,7 @@ static int do_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr,
return -EINVAL; return -EINVAL;
if (ts) { if (ts) {
expires = timespec_to_ktime(*ts); expires = timespec64_to_ktime(*ts);
timeout = &expires; timeout = &expires;
} }
...@@ -1080,7 +1080,7 @@ static int do_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr, ...@@ -1080,7 +1080,7 @@ static int do_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr,
static int do_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr, static int do_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr,
size_t msg_len, unsigned int __user *u_msg_prio, size_t msg_len, unsigned int __user *u_msg_prio,
struct timespec *ts) struct timespec64 *ts)
{ {
ssize_t ret; ssize_t ret;
struct msg_msg *msg_ptr; struct msg_msg *msg_ptr;
...@@ -1092,7 +1092,7 @@ static int do_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr, ...@@ -1092,7 +1092,7 @@ static int do_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr,
struct posix_msg_tree_node *new_leaf = NULL; struct posix_msg_tree_node *new_leaf = NULL;
if (ts) { if (ts) {
expires = timespec_to_ktime(*ts); expires = timespec64_to_ktime(*ts);
timeout = &expires; timeout = &expires;
} }
...@@ -1184,7 +1184,7 @@ SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr, ...@@ -1184,7 +1184,7 @@ SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr,
size_t, msg_len, unsigned int, msg_prio, size_t, msg_len, unsigned int, msg_prio,
const struct timespec __user *, u_abs_timeout) const struct timespec __user *, u_abs_timeout)
{ {
struct timespec ts, *p = NULL; struct timespec64 ts, *p = NULL;
if (u_abs_timeout) { if (u_abs_timeout) {
int res = prepare_timeout(u_abs_timeout, &ts); int res = prepare_timeout(u_abs_timeout, &ts);
if (res) if (res)
...@@ -1198,7 +1198,7 @@ SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr, ...@@ -1198,7 +1198,7 @@ SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr,
size_t, msg_len, unsigned int __user *, u_msg_prio, size_t, msg_len, unsigned int __user *, u_msg_prio,
const struct timespec __user *, u_abs_timeout) const struct timespec __user *, u_abs_timeout)
{ {
struct timespec ts, *p = NULL; struct timespec64 ts, *p = NULL;
if (u_abs_timeout) { if (u_abs_timeout) {
int res = prepare_timeout(u_abs_timeout, &ts); int res = prepare_timeout(u_abs_timeout, &ts);
if (res) if (res)
...@@ -1475,11 +1475,11 @@ COMPAT_SYSCALL_DEFINE4(mq_open, const char __user *, u_name, ...@@ -1475,11 +1475,11 @@ COMPAT_SYSCALL_DEFINE4(mq_open, const char __user *, u_name,
} }
static int compat_prepare_timeout(const struct compat_timespec __user *p, static int compat_prepare_timeout(const struct compat_timespec __user *p,
struct timespec *ts) struct timespec64 *ts)
{ {
if (compat_get_timespec(ts, p)) if (compat_get_timespec64(ts, p))
return -EFAULT; return -EFAULT;
if (!timespec_valid(ts)) if (!timespec64_valid(ts))
return -EINVAL; return -EINVAL;
return 0; return 0;
} }
...@@ -1489,7 +1489,7 @@ COMPAT_SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, ...@@ -1489,7 +1489,7 @@ COMPAT_SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes,
compat_size_t, msg_len, unsigned int, msg_prio, compat_size_t, msg_len, unsigned int, msg_prio,
const struct compat_timespec __user *, u_abs_timeout) const struct compat_timespec __user *, u_abs_timeout)
{ {
struct timespec ts, *p = NULL; struct timespec64 ts, *p = NULL;
if (u_abs_timeout) { if (u_abs_timeout) {
int res = compat_prepare_timeout(u_abs_timeout, &ts); int res = compat_prepare_timeout(u_abs_timeout, &ts);
if (res) if (res)
...@@ -1504,7 +1504,7 @@ COMPAT_SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, ...@@ -1504,7 +1504,7 @@ COMPAT_SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes,
compat_size_t, msg_len, unsigned int __user *, u_msg_prio, compat_size_t, msg_len, unsigned int __user *, u_msg_prio,
const struct compat_timespec __user *, u_abs_timeout) const struct compat_timespec __user *, u_abs_timeout)
{ {
struct timespec ts, *p = NULL; struct timespec64 ts, *p = NULL;
if (u_abs_timeout) { if (u_abs_timeout) {
int res = compat_prepare_timeout(u_abs_timeout, &ts); int res = compat_prepare_timeout(u_abs_timeout, &ts);
if (res) if (res)
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -5,12 +5,12 @@ ...@@ -5,12 +5,12 @@
* the individual syscalls instead. * the individual syscalls instead.
*/ */
#include <linux/unistd.h> #include <linux/unistd.h>
#include <linux/syscalls.h>
#ifdef __ARCH_WANT_SYS_IPC #ifdef __ARCH_WANT_SYS_IPC
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/ipc.h> #include <linux/ipc.h>
#include <linux/shm.h> #include <linux/shm.h>
#include <linux/syscalls.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second, 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, ...@@ -97,3 +97,91 @@ SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second,
} }
} }
#endif #endif
#ifdef CONFIG_COMPAT
#include <linux/compat.h>
#ifndef COMPAT_SHMLBA
#define COMPAT_SHMLBA SHMLBA
#endif
struct compat_ipc_kludge {
compat_uptr_t msgp;
compat_long_t msgtyp;
};
#ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC
COMPAT_SYSCALL_DEFINE6(ipc, u32, call, int, first, int, second,
u32, third, compat_uptr_t, ptr, u32, fifth)
{
int version;
u32 pad;
version = call >> 16; /* hack for backward compatibility */
call &= 0xffff;
switch (call) {
case SEMOP:
/* struct sembuf is the same on 32 and 64bit :)) */
return sys_semtimedop(first, compat_ptr(ptr), second, NULL);
case SEMTIMEDOP:
return compat_sys_semtimedop(first, compat_ptr(ptr), second,
compat_ptr(fifth));
case SEMGET:
return sys_semget(first, second, third);
case SEMCTL:
if (!ptr)
return -EINVAL;
if (get_user(pad, (u32 __user *) compat_ptr(ptr)))
return -EFAULT;
return compat_sys_semctl(first, second, third, pad);
case MSGSND:
return compat_sys_msgsnd(first, ptr, second, third);
case MSGRCV: {
void __user *uptr = compat_ptr(ptr);
if (first < 0 || second < 0)
return -EINVAL;
if (!version) {
struct compat_ipc_kludge ipck;
if (!uptr)
return -EINVAL;
if (copy_from_user(&ipck, uptr, sizeof(ipck)))
return -EFAULT;
return compat_sys_msgrcv(first, ipck.msgp, second,
ipck.msgtyp, third);
}
return compat_sys_msgrcv(first, ptr, second, fifth, third);
}
case MSGGET:
return sys_msgget(first, second);
case MSGCTL:
return compat_sys_msgctl(first, second, compat_ptr(ptr));
case SHMAT: {
int err;
unsigned long raddr;
if (version == 1)
return -EINVAL;
err = do_shmat(first, compat_ptr(ptr), second, &raddr,
COMPAT_SHMLBA);
if (err < 0)
return err;
return put_user(raddr, (compat_ulong_t *)compat_ptr(third));
}
case SHMDT:
return sys_shmdt(compat_ptr(ptr));
case SHMGET:
return sys_shmget(first, (unsigned)second, third);
case SHMCTL:
return compat_sys_shmctl(first, second, compat_ptr(ptr));
}
return -ENOSYS;
}
#endif
#endif
...@@ -194,4 +194,34 @@ int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids, ...@@ -194,4 +194,34 @@ int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids,
const struct ipc_ops *ops, struct ipc_params *params); const struct ipc_ops *ops, struct ipc_params *params);
void free_ipcs(struct ipc_namespace *ns, struct ipc_ids *ids, void free_ipcs(struct ipc_namespace *ns, struct ipc_ids *ids,
void (*free)(struct ipc_namespace *, struct kern_ipc_perm *)); void (*free)(struct ipc_namespace *, struct kern_ipc_perm *));
#ifdef CONFIG_COMPAT
#include <linux/compat.h>
struct compat_ipc_perm {
key_t key;
__compat_uid_t uid;
__compat_gid_t gid;
__compat_uid_t cuid;
__compat_gid_t cgid;
compat_mode_t mode;
unsigned short seq;
};
void to_compat_ipc_perm(struct compat_ipc_perm *, struct ipc64_perm *);
void to_compat_ipc64_perm(struct compat_ipc64_perm *, struct ipc64_perm *);
int get_compat_ipc_perm(struct ipc64_perm *, struct compat_ipc_perm __user *);
int get_compat_ipc64_perm(struct ipc64_perm *,
struct compat_ipc64_perm __user *);
static inline int compat_ipc_parse_version(int *cmd)
{
#ifdef CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION
int version = *cmd & IPC_64;
*cmd &= ~IPC_64;
return version;
#else
return IPC_64;
#endif
}
#endif
#endif #endif
...@@ -182,7 +182,7 @@ struct audit_context { ...@@ -182,7 +182,7 @@ struct audit_context {
mqd_t mqdes; mqd_t mqdes;
size_t msg_len; size_t msg_len;
unsigned int msg_prio; unsigned int msg_prio;
struct timespec abs_timeout; struct timespec64 abs_timeout;
} mq_sendrecv; } mq_sendrecv;
struct { struct {
int oflag; int oflag;
......
...@@ -1235,11 +1235,11 @@ static void show_special(struct audit_context *context, int *call_panic) ...@@ -1235,11 +1235,11 @@ static void show_special(struct audit_context *context, int *call_panic)
case AUDIT_MQ_SENDRECV: case AUDIT_MQ_SENDRECV:
audit_log_format(ab, audit_log_format(ab,
"mqdes=%d msg_len=%zd msg_prio=%u " "mqdes=%d msg_len=%zd msg_prio=%u "
"abs_timeout_sec=%ld abs_timeout_nsec=%ld", "abs_timeout_sec=%lld abs_timeout_nsec=%ld",
context->mq_sendrecv.mqdes, context->mq_sendrecv.mqdes,
context->mq_sendrecv.msg_len, context->mq_sendrecv.msg_len,
context->mq_sendrecv.msg_prio, context->mq_sendrecv.msg_prio,
context->mq_sendrecv.abs_timeout.tv_sec, (long long) context->mq_sendrecv.abs_timeout.tv_sec,
context->mq_sendrecv.abs_timeout.tv_nsec); context->mq_sendrecv.abs_timeout.tv_nsec);
break; break;
case AUDIT_MQ_NOTIFY: case AUDIT_MQ_NOTIFY:
...@@ -2083,15 +2083,15 @@ void __audit_mq_open(int oflag, umode_t mode, struct mq_attr *attr) ...@@ -2083,15 +2083,15 @@ void __audit_mq_open(int oflag, umode_t mode, struct mq_attr *attr)
* *
*/ */
void __audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, void __audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio,
const struct timespec *abs_timeout) const struct timespec64 *abs_timeout)
{ {
struct audit_context *context = current->audit_context; struct audit_context *context = current->audit_context;
struct timespec *p = &context->mq_sendrecv.abs_timeout; struct timespec64 *p = &context->mq_sendrecv.abs_timeout;
if (abs_timeout) if (abs_timeout)
memcpy(p, abs_timeout, sizeof(struct timespec)); memcpy(p, abs_timeout, sizeof(*p));
else else
memset(p, 0, sizeof(struct timespec)); memset(p, 0, sizeof(*p));
context->mq_sendrecv.mqdes = mqdes; context->mq_sendrecv.mqdes = mqdes;
context->mq_sendrecv.msg_len = msg_len; context->mq_sendrecv.msg_len = msg_len;
......
...@@ -200,29 +200,6 @@ int compat_put_timespec(const struct timespec *ts, void __user *uts) ...@@ -200,29 +200,6 @@ int compat_put_timespec(const struct timespec *ts, void __user *uts)
} }
EXPORT_SYMBOL_GPL(compat_put_timespec); EXPORT_SYMBOL_GPL(compat_put_timespec);
int compat_convert_timespec(struct timespec __user **kts,
const void __user *cts)
{
struct timespec ts;
struct timespec __user *uts;
if (!cts || COMPAT_USE_64BIT_TIME) {
*kts = (struct timespec __user *)cts;
return 0;
}
uts = compat_alloc_user_space(sizeof(ts));
if (!uts)
return -EFAULT;
if (compat_get_timespec(&ts, cts))
return -EFAULT;
if (copy_to_user(uts, &ts, sizeof(ts)))
return -EFAULT;
*kts = uts;
return 0;
}
int get_compat_itimerval(struct itimerval *o, const struct compat_itimerval __user *i) int get_compat_itimerval(struct itimerval *o, const struct compat_itimerval __user *i)
{ {
struct compat_itimerval v32; struct compat_itimerval v32;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment