Merge branch 'timers-2038-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull time/Y2038 updates from Thomas Gleixner: - Consolidate SySV IPC UAPI headers - Convert SySV IPC to the new COMPAT_32BIT_TIME mechanism - Cleanup the core interfaces and standardize on the ktime_get_* naming convention. - Convert the X86 platform ops to timespec64 - Remove the ugly temporary timespec64 hack * 'timers-2038-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (22 commits) x86: Convert x86_platform_ops to timespec64 timekeeping: Add more coarse clocktai/boottime interfaces timekeeping: Add ktime_get_coarse_with_offset timekeeping: Standardize on ktime_get_*() naming timekeeping: Clean up ktime_get_real_ts64 timekeeping: Remove timespec64 hack y2038: ipc: Redirect ipc(SEMTIMEDOP, ...) to compat_ksys_semtimedop y2038: ipc: Enable COMPAT_32BIT_TIME y2038: ipc: Use __kernel_timespec y2038: ipc: Report long times to user space y2038: ipc: Use ktime_get_real_seconds consistently y2038: xtensa: Extend sysvipc data structures y2038: powerpc: Extend sysvipc data structures y2038: sparc: Extend sysvipc data structures y2038: parisc: Extend sysvipc data structures y2038: mips: Extend sysvipc data structures y2038: arm64: Extend sysvipc compat data structures y2038: s390: Remove unneeded ipc uapi header files y2038: ia64: Remove unneeded ipc uapi header files y2038: alpha: Remove unneeded ipc uapi header files ...
This commit is contained in:
86
ipc/mqueue.c
86
ipc/mqueue.c
@@ -691,7 +691,7 @@ static void __do_notify(struct mqueue_inode_info *info)
|
||||
wake_up(&info->wait_q);
|
||||
}
|
||||
|
||||
static int prepare_timeout(const struct timespec __user *u_abs_timeout,
|
||||
static int prepare_timeout(const struct __kernel_timespec __user *u_abs_timeout,
|
||||
struct timespec64 *ts)
|
||||
{
|
||||
if (get_timespec64(ts, u_abs_timeout))
|
||||
@@ -1128,7 +1128,7 @@ out:
|
||||
|
||||
SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr,
|
||||
size_t, msg_len, unsigned int, msg_prio,
|
||||
const struct timespec __user *, u_abs_timeout)
|
||||
const struct __kernel_timespec __user *, u_abs_timeout)
|
||||
{
|
||||
struct timespec64 ts, *p = NULL;
|
||||
if (u_abs_timeout) {
|
||||
@@ -1142,7 +1142,7 @@ SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr,
|
||||
|
||||
SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr,
|
||||
size_t, msg_len, unsigned int __user *, u_msg_prio,
|
||||
const struct timespec __user *, u_abs_timeout)
|
||||
const struct __kernel_timespec __user *, u_abs_timeout)
|
||||
{
|
||||
struct timespec64 ts, *p = NULL;
|
||||
if (u_abs_timeout) {
|
||||
@@ -1420,6 +1420,47 @@ COMPAT_SYSCALL_DEFINE4(mq_open, const char __user *, u_name,
|
||||
return do_mq_open(u_name, oflag, mode, p);
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE2(mq_notify, mqd_t, mqdes,
|
||||
const struct compat_sigevent __user *, u_notification)
|
||||
{
|
||||
struct sigevent n, *p = NULL;
|
||||
if (u_notification) {
|
||||
if (get_compat_sigevent(&n, u_notification))
|
||||
return -EFAULT;
|
||||
if (n.sigev_notify == SIGEV_THREAD)
|
||||
n.sigev_value.sival_ptr = compat_ptr(n.sigev_value.sival_int);
|
||||
p = &n;
|
||||
}
|
||||
return do_mq_notify(mqdes, p);
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE3(mq_getsetattr, mqd_t, mqdes,
|
||||
const struct compat_mq_attr __user *, u_mqstat,
|
||||
struct compat_mq_attr __user *, u_omqstat)
|
||||
{
|
||||
int ret;
|
||||
struct mq_attr mqstat, omqstat;
|
||||
struct mq_attr *new = NULL, *old = NULL;
|
||||
|
||||
if (u_mqstat) {
|
||||
new = &mqstat;
|
||||
if (get_compat_mq_attr(new, u_mqstat))
|
||||
return -EFAULT;
|
||||
}
|
||||
if (u_omqstat)
|
||||
old = &omqstat;
|
||||
|
||||
ret = do_mq_getsetattr(mqdes, new, old);
|
||||
if (ret || !old)
|
||||
return ret;
|
||||
|
||||
if (put_compat_mq_attr(old, u_omqstat))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_COMPAT_32BIT_TIME
|
||||
static int compat_prepare_timeout(const struct compat_timespec __user *p,
|
||||
struct timespec64 *ts)
|
||||
{
|
||||
@@ -1459,45 +1500,6 @@ COMPAT_SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes,
|
||||
}
|
||||
return do_mq_timedreceive(mqdes, u_msg_ptr, msg_len, u_msg_prio, p);
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE2(mq_notify, mqd_t, mqdes,
|
||||
const struct compat_sigevent __user *, u_notification)
|
||||
{
|
||||
struct sigevent n, *p = NULL;
|
||||
if (u_notification) {
|
||||
if (get_compat_sigevent(&n, u_notification))
|
||||
return -EFAULT;
|
||||
if (n.sigev_notify == SIGEV_THREAD)
|
||||
n.sigev_value.sival_ptr = compat_ptr(n.sigev_value.sival_int);
|
||||
p = &n;
|
||||
}
|
||||
return do_mq_notify(mqdes, p);
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE3(mq_getsetattr, mqd_t, mqdes,
|
||||
const struct compat_mq_attr __user *, u_mqstat,
|
||||
struct compat_mq_attr __user *, u_omqstat)
|
||||
{
|
||||
int ret;
|
||||
struct mq_attr mqstat, omqstat;
|
||||
struct mq_attr *new = NULL, *old = NULL;
|
||||
|
||||
if (u_mqstat) {
|
||||
new = &mqstat;
|
||||
if (get_compat_mq_attr(new, u_mqstat))
|
||||
return -EFAULT;
|
||||
}
|
||||
if (u_omqstat)
|
||||
old = &omqstat;
|
||||
|
||||
ret = do_mq_getsetattr(mqdes, new, old);
|
||||
if (ret || !old)
|
||||
return ret;
|
||||
|
||||
if (put_compat_mq_attr(old, u_omqstat))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct inode_operations mqueue_dir_inode_operations = {
|
||||
|
||||
20
ipc/msg.c
20
ipc/msg.c
@@ -537,6 +537,11 @@ static int msgctl_stat(struct ipc_namespace *ns, int msqid,
|
||||
p->msg_stime = msq->q_stime;
|
||||
p->msg_rtime = msq->q_rtime;
|
||||
p->msg_ctime = msq->q_ctime;
|
||||
#ifndef CONFIG_64BIT
|
||||
p->msg_stime_high = msq->q_stime >> 32;
|
||||
p->msg_rtime_high = msq->q_rtime >> 32;
|
||||
p->msg_ctime_high = msq->q_ctime >> 32;
|
||||
#endif
|
||||
p->msg_cbytes = msq->q_cbytes;
|
||||
p->msg_qnum = msq->q_qnum;
|
||||
p->msg_qbytes = msq->q_qbytes;
|
||||
@@ -646,9 +651,12 @@ static int copy_compat_msqid_to_user(void __user *buf, struct msqid64_ds *in,
|
||||
struct compat_msqid64_ds v;
|
||||
memset(&v, 0, sizeof(v));
|
||||
to_compat_ipc64_perm(&v.msg_perm, &in->msg_perm);
|
||||
v.msg_stime = in->msg_stime;
|
||||
v.msg_rtime = in->msg_rtime;
|
||||
v.msg_ctime = in->msg_ctime;
|
||||
v.msg_stime = lower_32_bits(in->msg_stime);
|
||||
v.msg_stime_high = upper_32_bits(in->msg_stime);
|
||||
v.msg_rtime = lower_32_bits(in->msg_rtime);
|
||||
v.msg_rtime_high = upper_32_bits(in->msg_rtime);
|
||||
v.msg_ctime = lower_32_bits(in->msg_ctime);
|
||||
v.msg_ctime_high = upper_32_bits(in->msg_ctime);
|
||||
v.msg_cbytes = in->msg_cbytes;
|
||||
v.msg_qnum = in->msg_qnum;
|
||||
v.msg_qbytes = in->msg_qbytes;
|
||||
@@ -758,7 +766,7 @@ static inline int pipelined_send(struct msg_queue *msq, struct msg_msg *msg,
|
||||
WRITE_ONCE(msr->r_msg, ERR_PTR(-E2BIG));
|
||||
} else {
|
||||
ipc_update_pid(&msq->q_lrpid, task_pid(msr->r_tsk));
|
||||
msq->q_rtime = get_seconds();
|
||||
msq->q_rtime = ktime_get_real_seconds();
|
||||
|
||||
wake_q_add(wake_q, msr->r_tsk);
|
||||
WRITE_ONCE(msr->r_msg, msg);
|
||||
@@ -859,7 +867,7 @@ static long do_msgsnd(int msqid, long mtype, void __user *mtext,
|
||||
}
|
||||
|
||||
ipc_update_pid(&msq->q_lspid, task_tgid(current));
|
||||
msq->q_stime = get_seconds();
|
||||
msq->q_stime = ktime_get_real_seconds();
|
||||
|
||||
if (!pipelined_send(msq, msg, &wake_q)) {
|
||||
/* no one is waiting for this message, enqueue it */
|
||||
@@ -1087,7 +1095,7 @@ static long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, in
|
||||
|
||||
list_del(&msg->m_list);
|
||||
msq->q_qnum--;
|
||||
msq->q_rtime = get_seconds();
|
||||
msq->q_rtime = ktime_get_real_seconds();
|
||||
ipc_update_pid(&msq->q_lrpid, task_tgid(current));
|
||||
msq->q_cbytes -= msg->m_ts;
|
||||
atomic_sub(msg->m_ts, &ns->msg_bytes);
|
||||
|
||||
27
ipc/sem.c
27
ipc/sem.c
@@ -70,6 +70,7 @@
|
||||
* The worst-case behavior is nevertheless O(N^2) for N wakeups.
|
||||
*/
|
||||
|
||||
#include <linux/compat.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/init.h>
|
||||
@@ -104,7 +105,7 @@ struct sem {
|
||||
/* that alter the semaphore */
|
||||
struct list_head pending_const; /* pending single-sop operations */
|
||||
/* that do not alter the semaphore*/
|
||||
time_t sem_otime; /* candidate for sem_otime */
|
||||
time64_t sem_otime; /* candidate for sem_otime */
|
||||
} ____cacheline_aligned_in_smp;
|
||||
|
||||
/* One sem_array data structure for each set of semaphores in the system. */
|
||||
@@ -984,10 +985,10 @@ again:
|
||||
static void set_semotime(struct sem_array *sma, struct sembuf *sops)
|
||||
{
|
||||
if (sops == NULL) {
|
||||
sma->sems[0].sem_otime = get_seconds();
|
||||
sma->sems[0].sem_otime = ktime_get_real_seconds();
|
||||
} else {
|
||||
sma->sems[sops[0].sem_num].sem_otime =
|
||||
get_seconds();
|
||||
ktime_get_real_seconds();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1214,6 +1215,7 @@ static int semctl_stat(struct ipc_namespace *ns, int semid,
|
||||
int cmd, struct semid64_ds *semid64)
|
||||
{
|
||||
struct sem_array *sma;
|
||||
time64_t semotime;
|
||||
int id = 0;
|
||||
int err;
|
||||
|
||||
@@ -1257,8 +1259,13 @@ static int semctl_stat(struct ipc_namespace *ns, int semid,
|
||||
}
|
||||
|
||||
kernel_to_ipc64_perm(&sma->sem_perm, &semid64->sem_perm);
|
||||
semid64->sem_otime = get_semotime(sma);
|
||||
semotime = get_semotime(sma);
|
||||
semid64->sem_otime = semotime;
|
||||
semid64->sem_ctime = sma->sem_ctime;
|
||||
#ifndef CONFIG_64BIT
|
||||
semid64->sem_otime_high = semotime >> 32;
|
||||
semid64->sem_ctime_high = sma->sem_ctime >> 32;
|
||||
#endif
|
||||
semid64->sem_nsems = sma->sem_nsems;
|
||||
|
||||
ipc_unlock_object(&sma->sem_perm);
|
||||
@@ -1704,8 +1711,10 @@ static int copy_compat_semid_to_user(void __user *buf, struct semid64_ds *in,
|
||||
struct compat_semid64_ds v;
|
||||
memset(&v, 0, sizeof(v));
|
||||
to_compat_ipc64_perm(&v.sem_perm, &in->sem_perm);
|
||||
v.sem_otime = in->sem_otime;
|
||||
v.sem_ctime = in->sem_ctime;
|
||||
v.sem_otime = lower_32_bits(in->sem_otime);
|
||||
v.sem_otime_high = upper_32_bits(in->sem_otime);
|
||||
v.sem_ctime = lower_32_bits(in->sem_ctime);
|
||||
v.sem_ctime_high = upper_32_bits(in->sem_ctime);
|
||||
v.sem_nsems = in->sem_nsems;
|
||||
return copy_to_user(buf, &v, sizeof(v));
|
||||
} else {
|
||||
@@ -2168,7 +2177,7 @@ out_free:
|
||||
}
|
||||
|
||||
long ksys_semtimedop(int semid, struct sembuf __user *tsops,
|
||||
unsigned int nsops, const struct timespec __user *timeout)
|
||||
unsigned int nsops, const struct __kernel_timespec __user *timeout)
|
||||
{
|
||||
if (timeout) {
|
||||
struct timespec64 ts;
|
||||
@@ -2180,12 +2189,12 @@ long ksys_semtimedop(int semid, struct sembuf __user *tsops,
|
||||
}
|
||||
|
||||
SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
|
||||
unsigned int, nsops, const struct timespec __user *, timeout)
|
||||
unsigned int, nsops, const struct __kernel_timespec __user *, timeout)
|
||||
{
|
||||
return ksys_semtimedop(semid, tsops, nsops, timeout);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
#ifdef CONFIG_COMPAT_32BIT_TIME
|
||||
long compat_ksys_semtimedop(int semid, struct sembuf __user *tsems,
|
||||
unsigned int nsops,
|
||||
const struct compat_timespec __user *timeout)
|
||||
|
||||
14
ipc/shm.c
14
ipc/shm.c
@@ -1002,6 +1002,11 @@ static int shmctl_stat(struct ipc_namespace *ns, int shmid,
|
||||
tbuf->shm_atime = shp->shm_atim;
|
||||
tbuf->shm_dtime = shp->shm_dtim;
|
||||
tbuf->shm_ctime = shp->shm_ctim;
|
||||
#ifndef CONFIG_64BIT
|
||||
tbuf->shm_atime_high = shp->shm_atim >> 32;
|
||||
tbuf->shm_dtime_high = shp->shm_dtim >> 32;
|
||||
tbuf->shm_ctime_high = shp->shm_ctim >> 32;
|
||||
#endif
|
||||
tbuf->shm_cpid = pid_vnr(shp->shm_cprid);
|
||||
tbuf->shm_lpid = pid_vnr(shp->shm_lprid);
|
||||
tbuf->shm_nattch = shp->shm_nattch;
|
||||
@@ -1233,9 +1238,12 @@ static int copy_compat_shmid_to_user(void __user *buf, struct shmid64_ds *in,
|
||||
struct compat_shmid64_ds v;
|
||||
memset(&v, 0, sizeof(v));
|
||||
to_compat_ipc64_perm(&v.shm_perm, &in->shm_perm);
|
||||
v.shm_atime = in->shm_atime;
|
||||
v.shm_dtime = in->shm_dtime;
|
||||
v.shm_ctime = in->shm_ctime;
|
||||
v.shm_atime = lower_32_bits(in->shm_atime);
|
||||
v.shm_atime_high = upper_32_bits(in->shm_atime);
|
||||
v.shm_dtime = lower_32_bits(in->shm_dtime);
|
||||
v.shm_dtime_high = upper_32_bits(in->shm_dtime);
|
||||
v.shm_ctime = lower_32_bits(in->shm_ctime);
|
||||
v.shm_ctime_high = upper_32_bits(in->shm_ctime);
|
||||
v.shm_segsz = in->shm_segsz;
|
||||
v.shm_nattch = in->shm_nattch;
|
||||
v.shm_cpid = in->shm_cpid;
|
||||
|
||||
@@ -30,9 +30,14 @@ SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second,
|
||||
return ksys_semtimedop(first, (struct sembuf __user *)ptr,
|
||||
second, NULL);
|
||||
case SEMTIMEDOP:
|
||||
return ksys_semtimedop(first, (struct sembuf __user *)ptr,
|
||||
second,
|
||||
(const struct timespec __user *)fifth);
|
||||
if (IS_ENABLED(CONFIG_64BIT) || !IS_ENABLED(CONFIG_64BIT_TIME))
|
||||
return ksys_semtimedop(first, ptr, second,
|
||||
(const struct __kernel_timespec __user *)fifth);
|
||||
else if (IS_ENABLED(CONFIG_COMPAT_32BIT_TIME))
|
||||
return compat_ksys_semtimedop(first, ptr, second,
|
||||
(const struct compat_timespec __user *)fifth);
|
||||
else
|
||||
return -ENOSYS;
|
||||
|
||||
case SEMGET:
|
||||
return ksys_semget(first, second, third);
|
||||
@@ -130,6 +135,8 @@ COMPAT_SYSCALL_DEFINE6(ipc, u32, call, int, first, int, second,
|
||||
/* struct sembuf is the same on 32 and 64bit :)) */
|
||||
return ksys_semtimedop(first, compat_ptr(ptr), second, NULL);
|
||||
case SEMTIMEDOP:
|
||||
if (!IS_ENABLED(CONFIG_COMPAT_32BIT_TIME))
|
||||
return -ENOSYS;
|
||||
return compat_ksys_semtimedop(first, compat_ptr(ptr), second,
|
||||
compat_ptr(fifth));
|
||||
case SEMGET:
|
||||
|
||||
@@ -251,7 +251,7 @@ static inline int compat_ipc_parse_version(int *cmd)
|
||||
/* for __ARCH_WANT_SYS_IPC */
|
||||
long ksys_semtimedop(int semid, struct sembuf __user *tsops,
|
||||
unsigned int nsops,
|
||||
const struct timespec __user *timeout);
|
||||
const struct __kernel_timespec __user *timeout);
|
||||
long ksys_semget(key_t key, int nsems, int semflg);
|
||||
long ksys_semctl(int semid, int semnum, int cmd, unsigned long arg);
|
||||
long ksys_msgget(key_t key, int msgflg);
|
||||
@@ -265,10 +265,10 @@ long ksys_shmdt(char __user *shmaddr);
|
||||
long ksys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf);
|
||||
|
||||
/* for CONFIG_ARCH_WANT_OLD_COMPAT_IPC */
|
||||
#ifdef CONFIG_COMPAT
|
||||
long compat_ksys_semtimedop(int semid, struct sembuf __user *tsems,
|
||||
unsigned int nsops,
|
||||
const struct compat_timespec __user *timeout);
|
||||
#ifdef CONFIG_COMPAT
|
||||
long compat_ksys_semctl(int semid, int semnum, int cmd, int arg);
|
||||
long compat_ksys_msgctl(int msqid, int cmd, void __user *uptr);
|
||||
long compat_ksys_msgrcv(int msqid, compat_uptr_t msgp, compat_ssize_t msgsz,
|
||||
|
||||
Reference in New Issue
Block a user