compat_ioctl: pppoe: fix PPPOEIOCSFWD handling
[ Upstream commit 055d88242a6046a1ceac3167290f054c72571cd9 ] Support for handling the PPPOEIOCSFWD ioctl in compat mode was added in linux-2.5.69 along with hundreds of other commands, but was always broken sincen only the structure is compatible, but the command number is not, due to the size being sizeof(size_t), or at first sizeof(sizeof((struct sockaddr_pppox)), which is different on 64-bit architectures. Guillaume Nault adds: And the implementation was broken until 2016 (see 29e73269aa4d ("pppoe: fix reference counting in PPPoE proxy")), and nobody ever noticed. I should probably have removed this ioctl entirely instead of fixing it. Clearly, it has never been used. Fix it by adding a compat_ioctl handler for all pppoe variants that translates the command number and then calls the regular ioctl function. All other ioctl commands handled by pppoe are compatible between 32-bit and 64-bit, and require compat_ptr() conversion. This should apply to all stable kernels. Acked-by: Guillaume Nault <g.nault@alphalink.fr> Signed-off-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
2a0b2bd53e
commit
bf60393dbd
6 changed files with 25 additions and 3 deletions
|
@ -1152,6 +1152,9 @@ static const struct proto_ops pppoe_ops = {
|
||||||
.recvmsg = pppoe_recvmsg,
|
.recvmsg = pppoe_recvmsg,
|
||||||
.mmap = sock_no_mmap,
|
.mmap = sock_no_mmap,
|
||||||
.ioctl = pppox_ioctl,
|
.ioctl = pppox_ioctl,
|
||||||
|
#ifdef CONFIG_COMPAT
|
||||||
|
.compat_ioctl = pppox_compat_ioctl,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct pppox_proto pppoe_proto = {
|
static const struct pppox_proto pppoe_proto = {
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/compat.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/netdevice.h>
|
#include <linux/netdevice.h>
|
||||||
#include <linux/net.h>
|
#include <linux/net.h>
|
||||||
|
@ -103,6 +104,18 @@ int pppox_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
|
||||||
|
|
||||||
EXPORT_SYMBOL(pppox_ioctl);
|
EXPORT_SYMBOL(pppox_ioctl);
|
||||||
|
|
||||||
|
#ifdef CONFIG_COMPAT
|
||||||
|
int pppox_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
|
||||||
|
{
|
||||||
|
if (cmd == PPPOEIOCSFWD32)
|
||||||
|
cmd = PPPOEIOCSFWD;
|
||||||
|
|
||||||
|
return pppox_ioctl(sock, cmd, (unsigned long)compat_ptr(arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT_SYMBOL(pppox_compat_ioctl);
|
||||||
|
#endif
|
||||||
|
|
||||||
static int pppox_create(struct net *net, struct socket *sock, int protocol,
|
static int pppox_create(struct net *net, struct socket *sock, int protocol,
|
||||||
int kern)
|
int kern)
|
||||||
{
|
{
|
||||||
|
|
|
@ -674,6 +674,9 @@ static const struct proto_ops pptp_ops = {
|
||||||
.recvmsg = sock_no_recvmsg,
|
.recvmsg = sock_no_recvmsg,
|
||||||
.mmap = sock_no_mmap,
|
.mmap = sock_no_mmap,
|
||||||
.ioctl = pppox_ioctl,
|
.ioctl = pppox_ioctl,
|
||||||
|
#ifdef CONFIG_COMPAT
|
||||||
|
.compat_ioctl = pppox_compat_ioctl,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct pppox_proto pppox_pptp_proto = {
|
static const struct pppox_proto pppox_pptp_proto = {
|
||||||
|
|
|
@ -1016,9 +1016,6 @@ COMPATIBLE_IOCTL(PPPIOCDISCONN)
|
||||||
COMPATIBLE_IOCTL(PPPIOCATTCHAN)
|
COMPATIBLE_IOCTL(PPPIOCATTCHAN)
|
||||||
COMPATIBLE_IOCTL(PPPIOCGCHAN)
|
COMPATIBLE_IOCTL(PPPIOCGCHAN)
|
||||||
COMPATIBLE_IOCTL(PPPIOCGL2TPSTATS)
|
COMPATIBLE_IOCTL(PPPIOCGL2TPSTATS)
|
||||||
/* PPPOX */
|
|
||||||
COMPATIBLE_IOCTL(PPPOEIOCSFWD)
|
|
||||||
COMPATIBLE_IOCTL(PPPOEIOCDFWD)
|
|
||||||
/* ppdev */
|
/* ppdev */
|
||||||
COMPATIBLE_IOCTL(PPSETMODE)
|
COMPATIBLE_IOCTL(PPSETMODE)
|
||||||
COMPATIBLE_IOCTL(PPRSTATUS)
|
COMPATIBLE_IOCTL(PPRSTATUS)
|
||||||
|
|
|
@ -84,6 +84,9 @@ extern int register_pppox_proto(int proto_num, const struct pppox_proto *pp);
|
||||||
extern void unregister_pppox_proto(int proto_num);
|
extern void unregister_pppox_proto(int proto_num);
|
||||||
extern void pppox_unbind_sock(struct sock *sk);/* delete ppp-channel binding */
|
extern void pppox_unbind_sock(struct sock *sk);/* delete ppp-channel binding */
|
||||||
extern int pppox_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
|
extern int pppox_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
|
||||||
|
extern int pppox_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
|
||||||
|
|
||||||
|
#define PPPOEIOCSFWD32 _IOW(0xB1 ,0, compat_size_t)
|
||||||
|
|
||||||
/* PPPoX socket states */
|
/* PPPoX socket states */
|
||||||
enum {
|
enum {
|
||||||
|
|
|
@ -1805,6 +1805,9 @@ static const struct proto_ops pppol2tp_ops = {
|
||||||
.recvmsg = pppol2tp_recvmsg,
|
.recvmsg = pppol2tp_recvmsg,
|
||||||
.mmap = sock_no_mmap,
|
.mmap = sock_no_mmap,
|
||||||
.ioctl = pppox_ioctl,
|
.ioctl = pppox_ioctl,
|
||||||
|
#ifdef CONFIG_COMPAT
|
||||||
|
.compat_ioctl = pppox_compat_ioctl,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct pppox_proto pppol2tp_proto = {
|
static const struct pppox_proto pppol2tp_proto = {
|
||||||
|
|
Loading…
Add table
Reference in a new issue