compat_ioctl: pppoe: fix PPPOEIOCSFWD handling
[ Upstream commit055d88242a
] 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 (see29e73269aa
("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:
Родитель
13e82540b7
Коммит
d3d448bc50
|
@ -1137,6 +1137,9 @@ static const struct proto_ops pppoe_ops = {
|
|||
.recvmsg = pppoe_recvmsg,
|
||||
.mmap = sock_no_mmap,
|
||||
.ioctl = pppox_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = pppox_compat_ioctl,
|
||||
#endif
|
||||
};
|
||||
|
||||
static const struct pppox_proto pppoe_proto = {
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <linux/string.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/compat.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/netdevice.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);
|
||||
|
||||
#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,
|
||||
int kern)
|
||||
{
|
||||
|
|
|
@ -636,6 +636,9 @@ static const struct proto_ops pptp_ops = {
|
|||
.recvmsg = sock_no_recvmsg,
|
||||
.mmap = sock_no_mmap,
|
||||
.ioctl = pppox_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = pppox_compat_ioctl,
|
||||
#endif
|
||||
};
|
||||
|
||||
static const struct pppox_proto pppox_pptp_proto = {
|
||||
|
|
|
@ -1032,9 +1032,6 @@ COMPATIBLE_IOCTL(PPPIOCDISCONN)
|
|||
COMPATIBLE_IOCTL(PPPIOCATTCHAN)
|
||||
COMPATIBLE_IOCTL(PPPIOCGCHAN)
|
||||
COMPATIBLE_IOCTL(PPPIOCGL2TPSTATS)
|
||||
/* PPPOX */
|
||||
COMPATIBLE_IOCTL(PPPOEIOCSFWD)
|
||||
COMPATIBLE_IOCTL(PPPOEIOCDFWD)
|
||||
/* Big A */
|
||||
/* sparc only */
|
||||
/* Big Q for sound/OSS */
|
||||
|
|
|
@ -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 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_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
|
||||
|
||||
#define PPPOEIOCSFWD32 _IOW(0xB1 ,0, compat_size_t)
|
||||
|
||||
/* PPPoX socket states */
|
||||
enum {
|
||||
|
|
|
@ -1793,6 +1793,9 @@ static const struct proto_ops pppol2tp_ops = {
|
|||
.recvmsg = pppol2tp_recvmsg,
|
||||
.mmap = sock_no_mmap,
|
||||
.ioctl = pppox_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = pppox_compat_ioctl,
|
||||
#endif
|
||||
};
|
||||
|
||||
static const struct pppox_proto pppol2tp_proto = {
|
||||
|
|
Загрузка…
Ссылка в новой задаче