forked from luck/tmp_suning_uos_patched
compat_ioctl: handle PPPIOCGIDLE for 64-bit time_t
The ppp_idle structure is defined in terms of __kernel_time_t, which is defined as 'long' on all architectures, and this usage is not affected by the y2038 problem since it transports a time interval rather than an absolute time. However, the ppp user space defines the same structure as time_t, which may be 64-bit wide on new libc versions even on 32-bit architectures. It's easy enough to just handle both possible structure layouts on all architectures, to deal with the possibility that a user space ppp implementation comes with its own ppp_idle structure definition, as well as to document the fact that the driver is y2038-safe. Doing this also avoids the need for a special compat mode translation, since 32-bit and 64-bit kernels now support the same interfaces. The old 32-bit structure is also available on native 64-bit architectures now, but this is harmless. Cc: netdev@vger.kernel.org Cc: linux-ppp@vger.kernel.org Cc: Paul Mackerras <paulus@samba.org> Cc: "David S. Miller" <davem@davemloft.net> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
parent
5b6c02df50
commit
17c7e7f407
|
@ -378,6 +378,8 @@ an interface unit are:
|
|||
CONFIG_PPP_FILTER option is enabled, the set of packets which reset
|
||||
the transmit and receive idle timers is restricted to those which
|
||||
pass the `active' packet filter.
|
||||
Two versions of this command exist, to deal with user space
|
||||
expecting times as either 32-bit or 64-bit time_t seconds.
|
||||
|
||||
* PPPIOCSMAXCID sets the maximum connection-ID parameter (and thus the
|
||||
number of connection slots) for the TCP header compressor and
|
||||
|
|
|
@ -612,7 +612,8 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
struct ppp_file *pf;
|
||||
struct ppp *ppp;
|
||||
int err = -EFAULT, val, val2, i;
|
||||
struct ppp_idle idle;
|
||||
struct ppp_idle32 idle32;
|
||||
struct ppp_idle64 idle64;
|
||||
struct npioctl npi;
|
||||
int unit, cflags;
|
||||
struct slcompress *vj;
|
||||
|
@ -735,10 +736,18 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
err = 0;
|
||||
break;
|
||||
|
||||
case PPPIOCGIDLE:
|
||||
idle.xmit_idle = (jiffies - ppp->last_xmit) / HZ;
|
||||
idle.recv_idle = (jiffies - ppp->last_recv) / HZ;
|
||||
if (copy_to_user(argp, &idle, sizeof(idle)))
|
||||
case PPPIOCGIDLE32:
|
||||
idle32.xmit_idle = (jiffies - ppp->last_xmit) / HZ;
|
||||
idle32.recv_idle = (jiffies - ppp->last_recv) / HZ;
|
||||
if (copy_to_user(argp, &idle32, sizeof(idle32)))
|
||||
break;
|
||||
err = 0;
|
||||
break;
|
||||
|
||||
case PPPIOCGIDLE64:
|
||||
idle64.xmit_idle = (jiffies - ppp->last_xmit) / HZ;
|
||||
idle64.recv_idle = (jiffies - ppp->last_recv) / HZ;
|
||||
if (copy_to_user(argp, &idle64, sizeof(idle64)))
|
||||
break;
|
||||
err = 0;
|
||||
break;
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
|
||||
#include <linux/sort.h>
|
||||
|
||||
#ifdef CONFIG_BLOCK
|
||||
static int do_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
int err;
|
||||
|
@ -63,7 +64,6 @@ static int do_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
return vfs_ioctl(file, cmd, arg);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BLOCK
|
||||
struct compat_sg_req_info { /* used by SG_GET_REQUEST_TABLE ioctl() */
|
||||
char req_state;
|
||||
char orphan;
|
||||
|
@ -99,33 +99,6 @@ static int sg_grt_trans(struct file *file,
|
|||
}
|
||||
#endif /* CONFIG_BLOCK */
|
||||
|
||||
struct ppp_idle32 {
|
||||
compat_time_t xmit_idle;
|
||||
compat_time_t recv_idle;
|
||||
};
|
||||
#define PPPIOCGIDLE32 _IOR('t', 63, struct ppp_idle32)
|
||||
|
||||
static int ppp_gidle(struct file *file, unsigned int cmd,
|
||||
struct ppp_idle32 __user *idle32)
|
||||
{
|
||||
struct ppp_idle __user *idle;
|
||||
__kernel_time_t xmit, recv;
|
||||
int err;
|
||||
|
||||
idle = compat_alloc_user_space(sizeof(*idle));
|
||||
|
||||
err = do_ioctl(file, PPPIOCGIDLE, (unsigned long) idle);
|
||||
|
||||
if (!err) {
|
||||
if (get_user(xmit, &idle->xmit_idle) ||
|
||||
get_user(recv, &idle->recv_idle) ||
|
||||
put_user(xmit, &idle32->xmit_idle) ||
|
||||
put_user(recv, &idle32->recv_idle))
|
||||
err = -EFAULT;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* simple reversible transform to make our table more evenly
|
||||
* distributed after sorting.
|
||||
|
@ -192,7 +165,8 @@ COMPATIBLE_IOCTL(PPPIOCGDEBUG)
|
|||
COMPATIBLE_IOCTL(PPPIOCSDEBUG)
|
||||
/* PPPIOCSPASS is translated */
|
||||
/* PPPIOCSACTIVE is translated */
|
||||
/* PPPIOCGIDLE is translated */
|
||||
COMPATIBLE_IOCTL(PPPIOCGIDLE32)
|
||||
COMPATIBLE_IOCTL(PPPIOCGIDLE64)
|
||||
COMPATIBLE_IOCTL(PPPIOCNEWUNIT)
|
||||
COMPATIBLE_IOCTL(PPPIOCATTACH)
|
||||
COMPATIBLE_IOCTL(PPPIOCDETACH)
|
||||
|
@ -214,16 +188,14 @@ COMPATIBLE_IOCTL(PPPIOCGL2TPSTATS)
|
|||
static long do_ioctl_trans(unsigned int cmd,
|
||||
unsigned long arg, struct file *file)
|
||||
{
|
||||
#ifdef CONFIG_BLOCK
|
||||
void __user *argp = compat_ptr(arg);
|
||||
|
||||
switch (cmd) {
|
||||
case PPPIOCGIDLE32:
|
||||
return ppp_gidle(file, cmd, argp);
|
||||
#ifdef CONFIG_BLOCK
|
||||
case SG_GET_REQUEST_TABLE:
|
||||
return sg_grt_trans(file, cmd, argp);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
|
|
|
@ -104,6 +104,8 @@ struct pppol2tp_ioc_stats {
|
|||
#define PPPIOCGDEBUG _IOR('t', 65, int) /* Read debug level */
|
||||
#define PPPIOCSDEBUG _IOW('t', 64, int) /* Set debug level */
|
||||
#define PPPIOCGIDLE _IOR('t', 63, struct ppp_idle) /* get idle time */
|
||||
#define PPPIOCGIDLE32 _IOR('t', 63, struct ppp_idle32) /* 32-bit times */
|
||||
#define PPPIOCGIDLE64 _IOR('t', 63, struct ppp_idle64) /* 64-bit times */
|
||||
#define PPPIOCNEWUNIT _IOWR('t', 62, int) /* create new ppp unit */
|
||||
#define PPPIOCATTACH _IOW('t', 61, int) /* attach to ppp unit */
|
||||
#define PPPIOCDETACH _IOW('t', 60, int) /* obsolete, do not use */
|
||||
|
|
|
@ -142,10 +142,24 @@ struct ppp_comp_stats {
|
|||
/*
|
||||
* The following structure records the time in seconds since
|
||||
* the last NP packet was sent or received.
|
||||
*
|
||||
* Linux implements both 32-bit and 64-bit time_t versions
|
||||
* for compatibility with user space that defines ppp_idle
|
||||
* based on the libc time_t.
|
||||
*/
|
||||
struct ppp_idle {
|
||||
__kernel_time_t xmit_idle; /* time since last NP packet sent */
|
||||
__kernel_time_t recv_idle; /* time since last NP packet received */
|
||||
};
|
||||
|
||||
struct ppp_idle32 {
|
||||
__s32 xmit_idle; /* time since last NP packet sent */
|
||||
__s32 recv_idle; /* time since last NP packet received */
|
||||
};
|
||||
|
||||
struct ppp_idle64 {
|
||||
__s64 xmit_idle; /* time since last NP packet sent */
|
||||
__s64 recv_idle; /* time since last NP packet received */
|
||||
};
|
||||
|
||||
#endif /* _UAPI_PPP_DEFS_H_ */
|
||||
|
|
Loading…
Reference in New Issue
Block a user