diff options
Diffstat (limited to 'net/atm/ioctl.c')
-rw-r--r-- | net/atm/ioctl.c | 196 |
1 files changed, 98 insertions, 98 deletions
diff --git a/net/atm/ioctl.c b/net/atm/ioctl.c index 2ea40995dced..62dc8bfe6fe7 100644 --- a/net/atm/ioctl.c +++ b/net/atm/ioctl.c | |||
@@ -3,6 +3,7 @@ | |||
3 | /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ | 3 | /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ |
4 | /* 2003 John Levon <levon@movementarian.org> */ | 4 | /* 2003 John Levon <levon@movementarian.org> */ |
5 | 5 | ||
6 | #define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__ | ||
6 | 7 | ||
7 | #include <linux/module.h> | 8 | #include <linux/module.h> |
8 | #include <linux/kmod.h> | 9 | #include <linux/kmod.h> |
@@ -36,6 +37,7 @@ void register_atm_ioctl(struct atm_ioctl *ioctl) | |||
36 | list_add_tail(&ioctl->list, &ioctl_list); | 37 | list_add_tail(&ioctl->list, &ioctl_list); |
37 | mutex_unlock(&ioctl_mutex); | 38 | mutex_unlock(&ioctl_mutex); |
38 | } | 39 | } |
40 | EXPORT_SYMBOL(register_atm_ioctl); | ||
39 | 41 | ||
40 | void deregister_atm_ioctl(struct atm_ioctl *ioctl) | 42 | void deregister_atm_ioctl(struct atm_ioctl *ioctl) |
41 | { | 43 | { |
@@ -43,129 +45,128 @@ void deregister_atm_ioctl(struct atm_ioctl *ioctl) | |||
43 | list_del(&ioctl->list); | 45 | list_del(&ioctl->list); |
44 | mutex_unlock(&ioctl_mutex); | 46 | mutex_unlock(&ioctl_mutex); |
45 | } | 47 | } |
46 | |||
47 | EXPORT_SYMBOL(register_atm_ioctl); | ||
48 | EXPORT_SYMBOL(deregister_atm_ioctl); | 48 | EXPORT_SYMBOL(deregister_atm_ioctl); |
49 | 49 | ||
50 | static int do_vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg, int compat) | 50 | static int do_vcc_ioctl(struct socket *sock, unsigned int cmd, |
51 | unsigned long arg, int compat) | ||
51 | { | 52 | { |
52 | struct sock *sk = sock->sk; | 53 | struct sock *sk = sock->sk; |
53 | struct atm_vcc *vcc; | 54 | struct atm_vcc *vcc; |
54 | int error; | 55 | int error; |
55 | struct list_head * pos; | 56 | struct list_head *pos; |
56 | void __user *argp = (void __user *)arg; | 57 | void __user *argp = (void __user *)arg; |
57 | 58 | ||
58 | vcc = ATM_SD(sock); | 59 | vcc = ATM_SD(sock); |
59 | switch (cmd) { | 60 | switch (cmd) { |
60 | case SIOCOUTQ: | 61 | case SIOCOUTQ: |
61 | if (sock->state != SS_CONNECTED || | 62 | if (sock->state != SS_CONNECTED || |
62 | !test_bit(ATM_VF_READY, &vcc->flags)) { | 63 | !test_bit(ATM_VF_READY, &vcc->flags)) { |
63 | error = -EINVAL; | 64 | error = -EINVAL; |
64 | goto done; | 65 | goto done; |
65 | } | 66 | } |
66 | error = put_user(sk->sk_sndbuf - sk_wmem_alloc_get(sk), | 67 | error = put_user(sk->sk_sndbuf - sk_wmem_alloc_get(sk), |
67 | (int __user *) argp) ? -EFAULT : 0; | 68 | (int __user *)argp) ? -EFAULT : 0; |
69 | goto done; | ||
70 | case SIOCINQ: | ||
71 | { | ||
72 | struct sk_buff *skb; | ||
73 | |||
74 | if (sock->state != SS_CONNECTED) { | ||
75 | error = -EINVAL; | ||
68 | goto done; | 76 | goto done; |
69 | case SIOCINQ: | 77 | } |
70 | { | 78 | skb = skb_peek(&sk->sk_receive_queue); |
71 | struct sk_buff *skb; | 79 | error = put_user(skb ? skb->len : 0, |
72 | 80 | (int __user *)argp) ? -EFAULT : 0; | |
73 | if (sock->state != SS_CONNECTED) { | 81 | goto done; |
74 | error = -EINVAL; | 82 | } |
75 | goto done; | 83 | case SIOCGSTAMP: /* borrowed from IP */ |
76 | } | ||
77 | skb = skb_peek(&sk->sk_receive_queue); | ||
78 | error = put_user(skb ? skb->len : 0, | ||
79 | (int __user *)argp) ? -EFAULT : 0; | ||
80 | goto done; | ||
81 | } | ||
82 | case SIOCGSTAMP: /* borrowed from IP */ | ||
83 | #ifdef CONFIG_COMPAT | 84 | #ifdef CONFIG_COMPAT |
84 | if (compat) | 85 | if (compat) |
85 | error = compat_sock_get_timestamp(sk, argp); | 86 | error = compat_sock_get_timestamp(sk, argp); |
86 | else | 87 | else |
87 | #endif | 88 | #endif |
88 | error = sock_get_timestamp(sk, argp); | 89 | error = sock_get_timestamp(sk, argp); |
89 | goto done; | 90 | goto done; |
90 | case SIOCGSTAMPNS: /* borrowed from IP */ | 91 | case SIOCGSTAMPNS: /* borrowed from IP */ |
91 | #ifdef CONFIG_COMPAT | 92 | #ifdef CONFIG_COMPAT |
92 | if (compat) | 93 | if (compat) |
93 | error = compat_sock_get_timestampns(sk, argp); | 94 | error = compat_sock_get_timestampns(sk, argp); |
94 | else | 95 | else |
95 | #endif | 96 | #endif |
96 | error = sock_get_timestampns(sk, argp); | 97 | error = sock_get_timestampns(sk, argp); |
98 | goto done; | ||
99 | case ATM_SETSC: | ||
100 | if (net_ratelimit()) | ||
101 | pr_warning("ATM_SETSC is obsolete; used by %s:%d\n", | ||
102 | current->comm, task_pid_nr(current)); | ||
103 | error = 0; | ||
104 | goto done; | ||
105 | case ATMSIGD_CTRL: | ||
106 | if (!capable(CAP_NET_ADMIN)) { | ||
107 | error = -EPERM; | ||
97 | goto done; | 108 | goto done; |
98 | case ATM_SETSC: | 109 | } |
99 | if (net_ratelimit()) | 110 | /* |
100 | printk(KERN_WARNING "ATM_SETSC is obsolete; used by %s:%d\n", | 111 | * The user/kernel protocol for exchanging signalling |
101 | current->comm, task_pid_nr(current)); | 112 | * info uses kernel pointers as opaque references, |
102 | error = 0; | 113 | * so the holder of the file descriptor can scribble |
114 | * on the kernel... so we should make sure that we | ||
115 | * have the same privileges that /proc/kcore needs | ||
116 | */ | ||
117 | if (!capable(CAP_SYS_RAWIO)) { | ||
118 | error = -EPERM; | ||
103 | goto done; | 119 | goto done; |
104 | case ATMSIGD_CTRL: | 120 | } |
105 | if (!capable(CAP_NET_ADMIN)) { | ||
106 | error = -EPERM; | ||
107 | goto done; | ||
108 | } | ||
109 | /* | ||
110 | * The user/kernel protocol for exchanging signalling | ||
111 | * info uses kernel pointers as opaque references, | ||
112 | * so the holder of the file descriptor can scribble | ||
113 | * on the kernel... so we should make sure that we | ||
114 | * have the same privileges that /proc/kcore needs | ||
115 | */ | ||
116 | if (!capable(CAP_SYS_RAWIO)) { | ||
117 | error = -EPERM; | ||
118 | goto done; | ||
119 | } | ||
120 | #ifdef CONFIG_COMPAT | 121 | #ifdef CONFIG_COMPAT |
121 | /* WTF? I don't even want to _think_ about making this | 122 | /* WTF? I don't even want to _think_ about making this |
122 | work for 32-bit userspace. TBH I don't really want | 123 | work for 32-bit userspace. TBH I don't really want |
123 | to think about it at all. dwmw2. */ | 124 | to think about it at all. dwmw2. */ |
124 | if (compat) { | 125 | if (compat) { |
125 | if (net_ratelimit()) | 126 | if (net_ratelimit()) |
126 | printk(KERN_WARNING "32-bit task cannot be atmsigd\n"); | 127 | pr_warning("32-bit task cannot be atmsigd\n"); |
127 | error = -EINVAL; | 128 | error = -EINVAL; |
128 | goto done; | 129 | goto done; |
129 | } | 130 | } |
130 | #endif | 131 | #endif |
131 | error = sigd_attach(vcc); | 132 | error = sigd_attach(vcc); |
132 | if (!error) | 133 | if (!error) |
133 | sock->state = SS_CONNECTED; | 134 | sock->state = SS_CONNECTED; |
135 | goto done; | ||
136 | case ATM_SETBACKEND: | ||
137 | case ATM_NEWBACKENDIF: | ||
138 | { | ||
139 | atm_backend_t backend; | ||
140 | error = get_user(backend, (atm_backend_t __user *)argp); | ||
141 | if (error) | ||
134 | goto done; | 142 | goto done; |
135 | case ATM_SETBACKEND: | 143 | switch (backend) { |
136 | case ATM_NEWBACKENDIF: | 144 | case ATM_BACKEND_PPP: |
137 | { | 145 | request_module("pppoatm"); |
138 | atm_backend_t backend; | ||
139 | error = get_user(backend, (atm_backend_t __user *) argp); | ||
140 | if (error) | ||
141 | goto done; | ||
142 | switch (backend) { | ||
143 | case ATM_BACKEND_PPP: | ||
144 | request_module("pppoatm"); | ||
145 | break; | ||
146 | case ATM_BACKEND_BR2684: | ||
147 | request_module("br2684"); | ||
148 | break; | ||
149 | } | ||
150 | } | ||
151 | break; | ||
152 | case ATMMPC_CTRL: | ||
153 | case ATMMPC_DATA: | ||
154 | request_module("mpoa"); | ||
155 | break; | ||
156 | case ATMARPD_CTRL: | ||
157 | request_module("clip"); | ||
158 | break; | 146 | break; |
159 | case ATMLEC_CTRL: | 147 | case ATM_BACKEND_BR2684: |
160 | request_module("lec"); | 148 | request_module("br2684"); |
161 | break; | 149 | break; |
150 | } | ||
151 | break; | ||
152 | } | ||
153 | case ATMMPC_CTRL: | ||
154 | case ATMMPC_DATA: | ||
155 | request_module("mpoa"); | ||
156 | break; | ||
157 | case ATMARPD_CTRL: | ||
158 | request_module("clip"); | ||
159 | break; | ||
160 | case ATMLEC_CTRL: | ||
161 | request_module("lec"); | ||
162 | break; | ||
162 | } | 163 | } |
163 | 164 | ||
164 | error = -ENOIOCTLCMD; | 165 | error = -ENOIOCTLCMD; |
165 | 166 | ||
166 | mutex_lock(&ioctl_mutex); | 167 | mutex_lock(&ioctl_mutex); |
167 | list_for_each(pos, &ioctl_list) { | 168 | list_for_each(pos, &ioctl_list) { |
168 | struct atm_ioctl * ic = list_entry(pos, struct atm_ioctl, list); | 169 | struct atm_ioctl *ic = list_entry(pos, struct atm_ioctl, list); |
169 | if (try_module_get(ic->owner)) { | 170 | if (try_module_get(ic->owner)) { |
170 | error = ic->ioctl(sock, cmd, arg); | 171 | error = ic->ioctl(sock, cmd, arg); |
171 | module_put(ic->owner); | 172 | module_put(ic->owner); |
@@ -184,7 +185,6 @@ done: | |||
184 | return error; | 185 | return error; |
185 | } | 186 | } |
186 | 187 | ||
187 | |||
188 | int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | 188 | int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) |
189 | { | 189 | { |
190 | return do_vcc_ioctl(sock, cmd, arg, 0); | 190 | return do_vcc_ioctl(sock, cmd, arg, 0); |
@@ -287,8 +287,8 @@ static int do_atmif_sioc(struct socket *sock, unsigned int cmd, | |||
287 | sioc = compat_alloc_user_space(sizeof(*sioc)); | 287 | sioc = compat_alloc_user_space(sizeof(*sioc)); |
288 | sioc32 = compat_ptr(arg); | 288 | sioc32 = compat_ptr(arg); |
289 | 289 | ||
290 | if (copy_in_user(&sioc->number, &sioc32->number, 2 * sizeof(int)) | 290 | if (copy_in_user(&sioc->number, &sioc32->number, 2 * sizeof(int)) || |
291 | || get_user(data, &sioc32->arg)) | 291 | get_user(data, &sioc32->arg)) |
292 | return -EFAULT; | 292 | return -EFAULT; |
293 | datap = compat_ptr(data); | 293 | datap = compat_ptr(data); |
294 | if (put_user(datap, &sioc->arg)) | 294 | if (put_user(datap, &sioc->arg)) |