Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 122452
b: refs/heads/master
c: 8865c41
h: refs/heads/master
v: v3
  • Loading branch information
David Woodhouse authored and David S. Miller committed Dec 4, 2008
1 parent 0b46721 commit 287b66e
Show file tree
Hide file tree
Showing 9 changed files with 165 additions and 31 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: dcd39c90290297f6e6ed8a04bb20da7ac2b043c5
refs/heads/master: 8865c418caf4e9dd2c24bdfae3a5a4106e143e60
17 changes: 14 additions & 3 deletions trunk/include/linux/atm.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,10 +231,21 @@ static __inline__ int atmpvc_addr_in_use(struct sockaddr_atmpvc addr)
*/

struct atmif_sioc {
int number;
int length;
void __user *arg;
int number;
int length;
void __user *arg;
};

#ifdef __KERNEL__
#ifdef CONFIG_COMPAT
#include <linux/compat.h>
struct compat_atmif_sioc {
int number;
int length;
compat_uptr_t arg;
};
#endif
#endif

typedef unsigned short atm_backend_t;
#endif
15 changes: 15 additions & 0 deletions trunk/include/linux/atmdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ struct atm_dev_stats {
/* use backend to make new if */
#define ATM_ADDPARTY _IOW('a', ATMIOC_SPECIAL+4,struct atm_iobuf)
/* add party to p2mp call */
#ifdef CONFIG_COMPAT
/* It actually takes struct sockaddr_atmsvc, not struct atm_iobuf */
#define COMPAT_ATM_ADDPARTY _IOW('a', ATMIOC_SPECIAL+4,struct compat_atm_iobuf)
#endif
#define ATM_DROPPARTY _IOW('a', ATMIOC_SPECIAL+5,int)
/* drop party from p2mp call */

Expand Down Expand Up @@ -224,6 +228,13 @@ struct atm_cirange {
extern struct proc_dir_entry *atm_proc_root;
#endif

#ifdef CONFIG_COMPAT
#include <linux/compat.h>
struct compat_atm_iobuf {
int length;
compat_uptr_t buffer;
};
#endif

struct k_atm_aal_stats {
#define __HANDLE_ITEM(i) atomic_t i
Expand Down Expand Up @@ -379,6 +390,10 @@ struct atmdev_ops { /* only send is required */
int (*open)(struct atm_vcc *vcc);
void (*close)(struct atm_vcc *vcc);
int (*ioctl)(struct atm_dev *dev,unsigned int cmd,void __user *arg);
#ifdef CONFIG_COMPAT
int (*compat_ioctl)(struct atm_dev *dev,unsigned int cmd,
void __user *arg);
#endif
int (*getsockopt)(struct atm_vcc *vcc,int level,int optname,
void __user *optval,int optlen);
int (*setsockopt)(struct atm_vcc *vcc,int level,int optname,
Expand Down
1 change: 1 addition & 0 deletions trunk/net/atm/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
size_t total_len);
unsigned int vcc_poll(struct file *file, struct socket *sock, poll_table *wait);
int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
int vcc_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
int vcc_setsockopt(struct socket *sock, int level, int optname,
char __user *optval, int optlen);
int vcc_getsockopt(struct socket *sock, int level, int optname,
Expand Down
49 changes: 43 additions & 6 deletions trunk/net/atm/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <linux/atmlec.h>
#include <linux/mutex.h>
#include <asm/ioctls.h>
#include <net/compat.h>

#include "resources.h"
#include "signaling.h" /* for WAITING and sigd_attach */
Expand Down Expand Up @@ -46,7 +47,7 @@ void deregister_atm_ioctl(struct atm_ioctl *ioctl)
EXPORT_SYMBOL(register_atm_ioctl);
EXPORT_SYMBOL(deregister_atm_ioctl);

int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
static int do_vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg, int compat)
{
struct sock *sk = sock->sk;
struct atm_vcc *vcc;
Expand Down Expand Up @@ -80,13 +81,25 @@ int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
goto done;
}
case SIOCGSTAMP: /* borrowed from IP */
error = sock_get_timestamp(sk, argp);
#ifdef CONFIG_COMPAT
if (compat)
error = compat_sock_get_timestamp(sk, argp);
else
#endif
error = sock_get_timestamp(sk, argp);
goto done;
case SIOCGSTAMPNS: /* borrowed from IP */
error = sock_get_timestampns(sk, argp);
#ifdef CONFIG_COMPAT
if (compat)
error = compat_sock_get_timestampns(sk, argp);
else
#endif
error = sock_get_timestampns(sk, argp);
goto done;
case ATM_SETSC:
printk(KERN_WARNING "ATM_SETSC is obsolete\n");
if (net_ratelimit())
printk(KERN_WARNING "ATM_SETSC is obsolete; used by %s:%d\n",
current->comm, task_pid_nr(current));
error = 0;
goto done;
case ATMSIGD_CTRL:
Expand All @@ -99,12 +112,23 @@ int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
* info uses kernel pointers as opaque references,
* so the holder of the file descriptor can scribble
* on the kernel... so we should make sure that we
* have the same privledges that /proc/kcore needs
* have the same privileges that /proc/kcore needs
*/
if (!capable(CAP_SYS_RAWIO)) {
error = -EPERM;
goto done;
}
#ifdef CONFIG_COMPAT
/* WTF? I don't even want to _think_ about making this
work for 32-bit userspace. TBH I don't really want
to think about it at all. dwmw2. */
if (compat) {
if (net_ratelimit())
printk(KERN_WARNING "32-bit task cannot be atmsigd\n");
error = -EINVAL;
goto done;
}
#endif
error = sigd_attach(vcc);
if (!error)
sock->state = SS_CONNECTED;
Expand Down Expand Up @@ -155,8 +179,21 @@ int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
if (error != -ENOIOCTLCMD)
goto done;

error = atm_dev_ioctl(cmd, argp);
error = atm_dev_ioctl(cmd, argp, compat);

done:
return error;
}


int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
return do_vcc_ioctl(sock, cmd, arg, 0);
}

#ifdef CONFIG_COMPAT
int vcc_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
return do_vcc_ioctl(sock, cmd, arg, 1);
}
#endif
3 changes: 3 additions & 0 deletions trunk/net/atm/pvc.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ static const struct proto_ops pvc_proto_ops = {
.getname = pvc_getname,
.poll = vcc_poll,
.ioctl = vcc_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = vcc_compat_ioctl,
#endif
.listen = sock_no_listen,
.shutdown = pvc_shutdown,
.setsockopt = pvc_setsockopt,
Expand Down
88 changes: 68 additions & 20 deletions trunk/net/atm/resources.c
Original file line number Diff line number Diff line change
Expand Up @@ -195,20 +195,39 @@ static int fetch_stats(struct atm_dev *dev, struct atm_dev_stats __user *arg, in
}


int atm_dev_ioctl(unsigned int cmd, void __user *arg)
int atm_dev_ioctl(unsigned int cmd, void __user *arg, int compat)
{
void __user *buf;
int error, len, number, size = 0;
struct atm_dev *dev;
struct list_head *p;
int *tmp_buf, *tmp_p;
struct atm_iobuf __user *iobuf = arg;
struct atmif_sioc __user *sioc = arg;
int __user *sioc_len;
int __user *iobuf_len;

#ifndef CONFIG_COMPAT
compat = 0; /* Just so the compiler _knows_ */
#endif

switch (cmd) {
case ATM_GETNAMES:
if (get_user(buf, &iobuf->buffer))
return -EFAULT;
if (get_user(len, &iobuf->length))

if (compat) {
#ifdef CONFIG_COMPAT
struct compat_atm_iobuf __user *ciobuf = arg;
compat_uptr_t cbuf;
iobuf_len = &ciobuf->length;
if (get_user(cbuf, &ciobuf->buffer))
return -EFAULT;
buf = compat_ptr(cbuf);
#endif
} else {
struct atm_iobuf __user *iobuf = arg;
iobuf_len = &iobuf->length;
if (get_user(buf, &iobuf->buffer))
return -EFAULT;
}
if (get_user(len, iobuf_len))
return -EFAULT;
mutex_lock(&atm_dev_mutex);
list_for_each(p, &atm_devs)
Expand All @@ -229,21 +248,40 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg)
}
mutex_unlock(&atm_dev_mutex);
error = ((copy_to_user(buf, tmp_buf, size)) ||
put_user(size, &iobuf->length))
put_user(size, iobuf_len))
? -EFAULT : 0;
kfree(tmp_buf);
return error;
default:
break;
}

if (get_user(buf, &sioc->arg))
return -EFAULT;
if (get_user(len, &sioc->length))
return -EFAULT;
if (get_user(number, &sioc->number))
return -EFAULT;

if (compat) {
#ifdef CONFIG_COMPAT
struct compat_atmif_sioc __user *csioc = arg;
compat_uptr_t carg;

sioc_len = &csioc->length;
if (get_user(carg, &csioc->arg))
return -EFAULT;
buf = compat_ptr(carg);

if (get_user(len, &csioc->length))
return -EFAULT;
if (get_user(number, &csioc->number))
return -EFAULT;
#endif
} else {
struct atmif_sioc __user *sioc = arg;

sioc_len = &sioc->length;
if (get_user(buf, &sioc->arg))
return -EFAULT;
if (get_user(len, &sioc->length))
return -EFAULT;
if (get_user(number, &sioc->number))
return -EFAULT;
}
if (!(dev = try_then_request_module(atm_dev_lookup(number),
"atm-device-%d", number)))
return -ENODEV;
Expand Down Expand Up @@ -358,7 +396,7 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg)
size = error;
/* may return 0, but later on size == 0 means "don't
write the length" */
error = put_user(size, &sioc->length)
error = put_user(size, sioc_len)
? -EFAULT : 0;
goto done;
case ATM_SETLOOP:
Expand All @@ -380,19 +418,29 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg)
}
/* fall through */
default:
if (!dev->ops->ioctl) {
error = -EINVAL;
goto done;
if (compat) {
#ifdef CONFIG_COMPAT
if (!dev->ops->compat_ioctl) {
error = -EINVAL;
goto done;
}
size = dev->ops->compat_ioctl(dev, cmd, buf);
#endif
} else {
if (!dev->ops->ioctl) {
error = -EINVAL;
goto done;
}
size = dev->ops->ioctl(dev, cmd, buf);
}
size = dev->ops->ioctl(dev, cmd, buf);
if (size < 0) {
error = (size == -ENOIOCTLCMD ? -EINVAL : size);
goto done;
}
}

if (size)
error = put_user(size, &sioc->length)
error = put_user(size, sioc_len)
? -EFAULT : 0;
else
error = 0;
Expand Down
2 changes: 1 addition & 1 deletion trunk/net/atm/resources.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
extern struct list_head atm_devs;
extern struct mutex atm_dev_mutex;

int atm_dev_ioctl(unsigned int cmd, void __user *arg);
int atm_dev_ioctl(unsigned int cmd, void __user *arg, int compat);


#ifdef CONFIG_PROC_FS
Expand Down
19 changes: 19 additions & 0 deletions trunk/net/atm/svc.c
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,22 @@ static int svc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
return error;
}

#ifdef CONFIG_COMPAT
static int svc_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
/* The definition of ATM_ADDPARTY uses the size of struct atm_iobuf.
But actually it takes a struct sockaddr_atmsvc, which doesn't need
compat handling. So all we have to do is fix up cmd... */
if (cmd == COMPAT_ATM_ADDPARTY)
cmd = ATM_ADDPARTY;

if (cmd == ATM_ADDPARTY || cmd == ATM_DROPPARTY)
return svc_ioctl(sock, cmd, arg);
else
return vcc_compat_ioctl(sock, cmd, arg);
}
#endif /* CONFIG_COMPAT */

static const struct proto_ops svc_proto_ops = {
.family = PF_ATMSVC,
.owner = THIS_MODULE,
Expand All @@ -616,6 +632,9 @@ static const struct proto_ops svc_proto_ops = {
.getname = svc_getname,
.poll = vcc_poll,
.ioctl = svc_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = svc_compat_ioctl,
#endif
.listen = svc_listen,
.shutdown = svc_shutdown,
.setsockopt = svc_setsockopt,
Expand Down

0 comments on commit 287b66e

Please sign in to comment.