Skip to content

Commit 17c7e7f

Browse files
committed
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: [email protected] Cc: [email protected] Cc: Paul Mackerras <[email protected]> Cc: "David S. Miller" <[email protected]> Signed-off-by: Arnd Bergmann <[email protected]>
1 parent 5b6c02d commit 17c7e7f

File tree

5 files changed

+37
-38
lines changed

5 files changed

+37
-38
lines changed

Documentation/networking/ppp_generic.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,8 @@ an interface unit are:
378378
CONFIG_PPP_FILTER option is enabled, the set of packets which reset
379379
the transmit and receive idle timers is restricted to those which
380380
pass the `active' packet filter.
381+
Two versions of this command exist, to deal with user space
382+
expecting times as either 32-bit or 64-bit time_t seconds.
381383

382384
* PPPIOCSMAXCID sets the maximum connection-ID parameter (and thus the
383385
number of connection slots) for the TCP header compressor and

drivers/net/ppp/ppp_generic.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,8 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
612612
struct ppp_file *pf;
613613
struct ppp *ppp;
614614
int err = -EFAULT, val, val2, i;
615-
struct ppp_idle idle;
615+
struct ppp_idle32 idle32;
616+
struct ppp_idle64 idle64;
616617
struct npioctl npi;
617618
int unit, cflags;
618619
struct slcompress *vj;
@@ -735,10 +736,18 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
735736
err = 0;
736737
break;
737738

738-
case PPPIOCGIDLE:
739-
idle.xmit_idle = (jiffies - ppp->last_xmit) / HZ;
740-
idle.recv_idle = (jiffies - ppp->last_recv) / HZ;
741-
if (copy_to_user(argp, &idle, sizeof(idle)))
739+
case PPPIOCGIDLE32:
740+
idle32.xmit_idle = (jiffies - ppp->last_xmit) / HZ;
741+
idle32.recv_idle = (jiffies - ppp->last_recv) / HZ;
742+
if (copy_to_user(argp, &idle32, sizeof(idle32)))
743+
break;
744+
err = 0;
745+
break;
746+
747+
case PPPIOCGIDLE64:
748+
idle64.xmit_idle = (jiffies - ppp->last_xmit) / HZ;
749+
idle64.recv_idle = (jiffies - ppp->last_recv) / HZ;
750+
if (copy_to_user(argp, &idle64, sizeof(idle64)))
742751
break;
743752
err = 0;
744753
break;

fs/compat_ioctl.c

Lines changed: 5 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252

5353
#include <linux/sort.h>
5454

55+
#ifdef CONFIG_BLOCK
5556
static int do_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
5657
{
5758
int err;
@@ -63,7 +64,6 @@ static int do_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
6364
return vfs_ioctl(file, cmd, arg);
6465
}
6566

66-
#ifdef CONFIG_BLOCK
6767
struct compat_sg_req_info { /* used by SG_GET_REQUEST_TABLE ioctl() */
6868
char req_state;
6969
char orphan;
@@ -99,33 +99,6 @@ static int sg_grt_trans(struct file *file,
9999
}
100100
#endif /* CONFIG_BLOCK */
101101

102-
struct ppp_idle32 {
103-
compat_time_t xmit_idle;
104-
compat_time_t recv_idle;
105-
};
106-
#define PPPIOCGIDLE32 _IOR('t', 63, struct ppp_idle32)
107-
108-
static int ppp_gidle(struct file *file, unsigned int cmd,
109-
struct ppp_idle32 __user *idle32)
110-
{
111-
struct ppp_idle __user *idle;
112-
__kernel_time_t xmit, recv;
113-
int err;
114-
115-
idle = compat_alloc_user_space(sizeof(*idle));
116-
117-
err = do_ioctl(file, PPPIOCGIDLE, (unsigned long) idle);
118-
119-
if (!err) {
120-
if (get_user(xmit, &idle->xmit_idle) ||
121-
get_user(recv, &idle->recv_idle) ||
122-
put_user(xmit, &idle32->xmit_idle) ||
123-
put_user(recv, &idle32->recv_idle))
124-
err = -EFAULT;
125-
}
126-
return err;
127-
}
128-
129102
/*
130103
* simple reversible transform to make our table more evenly
131104
* distributed after sorting.
@@ -192,7 +165,8 @@ COMPATIBLE_IOCTL(PPPIOCGDEBUG)
192165
COMPATIBLE_IOCTL(PPPIOCSDEBUG)
193166
/* PPPIOCSPASS is translated */
194167
/* PPPIOCSACTIVE is translated */
195-
/* PPPIOCGIDLE is translated */
168+
COMPATIBLE_IOCTL(PPPIOCGIDLE32)
169+
COMPATIBLE_IOCTL(PPPIOCGIDLE64)
196170
COMPATIBLE_IOCTL(PPPIOCNEWUNIT)
197171
COMPATIBLE_IOCTL(PPPIOCATTACH)
198172
COMPATIBLE_IOCTL(PPPIOCDETACH)
@@ -214,16 +188,14 @@ COMPATIBLE_IOCTL(PPPIOCGL2TPSTATS)
214188
static long do_ioctl_trans(unsigned int cmd,
215189
unsigned long arg, struct file *file)
216190
{
191+
#ifdef CONFIG_BLOCK
217192
void __user *argp = compat_ptr(arg);
218193

219194
switch (cmd) {
220-
case PPPIOCGIDLE32:
221-
return ppp_gidle(file, cmd, argp);
222-
#ifdef CONFIG_BLOCK
223195
case SG_GET_REQUEST_TABLE:
224196
return sg_grt_trans(file, cmd, argp);
225-
#endif
226197
}
198+
#endif
227199

228200
return -ENOIOCTLCMD;
229201
}

include/uapi/linux/ppp-ioctl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ struct pppol2tp_ioc_stats {
104104
#define PPPIOCGDEBUG _IOR('t', 65, int) /* Read debug level */
105105
#define PPPIOCSDEBUG _IOW('t', 64, int) /* Set debug level */
106106
#define PPPIOCGIDLE _IOR('t', 63, struct ppp_idle) /* get idle time */
107+
#define PPPIOCGIDLE32 _IOR('t', 63, struct ppp_idle32) /* 32-bit times */
108+
#define PPPIOCGIDLE64 _IOR('t', 63, struct ppp_idle64) /* 64-bit times */
107109
#define PPPIOCNEWUNIT _IOWR('t', 62, int) /* create new ppp unit */
108110
#define PPPIOCATTACH _IOW('t', 61, int) /* attach to ppp unit */
109111
#define PPPIOCDETACH _IOW('t', 60, int) /* obsolete, do not use */

include/uapi/linux/ppp_defs.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,10 +142,24 @@ struct ppp_comp_stats {
142142
/*
143143
* The following structure records the time in seconds since
144144
* the last NP packet was sent or received.
145+
*
146+
* Linux implements both 32-bit and 64-bit time_t versions
147+
* for compatibility with user space that defines ppp_idle
148+
* based on the libc time_t.
145149
*/
146150
struct ppp_idle {
147151
__kernel_time_t xmit_idle; /* time since last NP packet sent */
148152
__kernel_time_t recv_idle; /* time since last NP packet received */
149153
};
150154

155+
struct ppp_idle32 {
156+
__s32 xmit_idle; /* time since last NP packet sent */
157+
__s32 recv_idle; /* time since last NP packet received */
158+
};
159+
160+
struct ppp_idle64 {
161+
__s64 xmit_idle; /* time since last NP packet sent */
162+
__s64 recv_idle; /* time since last NP packet received */
163+
};
164+
151165
#endif /* _UAPI_PPP_DEFS_H_ */

0 commit comments

Comments
 (0)