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