aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/linux-2.6/xfs_ioctl32.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_ioctl32.c')
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl32.c207
1 files changed, 120 insertions, 87 deletions
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c
index 620bb2d6d26c..35edc054fb99 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl32.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl32.c
@@ -43,55 +43,62 @@
43#include "xfs_error.h" 43#include "xfs_error.h"
44#include "xfs_dfrag.h" 44#include "xfs_dfrag.h"
45#include "xfs_vnodeops.h" 45#include "xfs_vnodeops.h"
46#include "xfs_fsops.h"
47#include "xfs_ioctl.h"
46#include "xfs_ioctl32.h" 48#include "xfs_ioctl32.h"
47 49
48#define _NATIVE_IOC(cmd, type) \ 50#define _NATIVE_IOC(cmd, type) \
49 _IOC(_IOC_DIR(cmd), _IOC_TYPE(cmd), _IOC_NR(cmd), sizeof(type)) 51 _IOC(_IOC_DIR(cmd), _IOC_TYPE(cmd), _IOC_NR(cmd), sizeof(type))
50 52
51#ifdef BROKEN_X86_ALIGNMENT 53#ifdef BROKEN_X86_ALIGNMENT
52STATIC unsigned long 54STATIC int
53xfs_ioctl32_flock( 55xfs_compat_flock64_copyin(
54 unsigned long arg) 56 xfs_flock64_t *bf,
57 compat_xfs_flock64_t __user *arg32)
55{ 58{
56 compat_xfs_flock64_t __user *p32 = (void __user *)arg; 59 if (get_user(bf->l_type, &arg32->l_type) ||
57 xfs_flock64_t __user *p = compat_alloc_user_space(sizeof(*p)); 60 get_user(bf->l_whence, &arg32->l_whence) ||
58 61 get_user(bf->l_start, &arg32->l_start) ||
59 if (copy_in_user(&p->l_type, &p32->l_type, sizeof(s16)) || 62 get_user(bf->l_len, &arg32->l_len) ||
60 copy_in_user(&p->l_whence, &p32->l_whence, sizeof(s16)) || 63 get_user(bf->l_sysid, &arg32->l_sysid) ||
61 copy_in_user(&p->l_start, &p32->l_start, sizeof(s64)) || 64 get_user(bf->l_pid, &arg32->l_pid) ||
62 copy_in_user(&p->l_len, &p32->l_len, sizeof(s64)) || 65 copy_from_user(bf->l_pad, &arg32->l_pad, 4*sizeof(u32)))
63 copy_in_user(&p->l_sysid, &p32->l_sysid, sizeof(s32)) || 66 return -XFS_ERROR(EFAULT);
64 copy_in_user(&p->l_pid, &p32->l_pid, sizeof(u32)) || 67 return 0;
65 copy_in_user(&p->l_pad, &p32->l_pad, 4*sizeof(u32)))
66 return -EFAULT;
67
68 return (unsigned long)p;
69} 68}
70 69
71STATIC unsigned long xfs_ioctl32_geom_v1(unsigned long arg) 70STATIC int
71xfs_compat_ioc_fsgeometry_v1(
72 struct xfs_mount *mp,
73 compat_xfs_fsop_geom_v1_t __user *arg32)
72{ 74{
73 compat_xfs_fsop_geom_v1_t __user *p32 = (void __user *)arg; 75 xfs_fsop_geom_t fsgeo;
74 xfs_fsop_geom_v1_t __user *p = compat_alloc_user_space(sizeof(*p)); 76 int error;
75 77
76 if (copy_in_user(p, p32, sizeof(*p32))) 78 error = xfs_fs_geometry(mp, &fsgeo, 3);
77 return -EFAULT; 79 if (error)
78 return (unsigned long)p; 80 return -error;
81 /* The 32-bit variant simply has some padding at the end */
82 if (copy_to_user(arg32, &fsgeo, sizeof(struct compat_xfs_fsop_geom_v1)))
83 return -XFS_ERROR(EFAULT);
84 return 0;
79} 85}
80 86
81STATIC int xfs_inumbers_fmt_compat( 87STATIC int
82 void __user *ubuffer, 88xfs_inumbers_fmt_compat(
83 const xfs_inogrp_t *buffer, 89 void __user *ubuffer,
84 long count, 90 const xfs_inogrp_t *buffer,
85 long *written) 91 long count,
92 long *written)
86{ 93{
87 compat_xfs_inogrp_t __user *p32 = ubuffer; 94 compat_xfs_inogrp_t __user *p32 = ubuffer;
88 long i; 95 long i;
89 96
90 for (i = 0; i < count; i++) { 97 for (i = 0; i < count; i++) {
91 if (put_user(buffer[i].xi_startino, &p32[i].xi_startino) || 98 if (put_user(buffer[i].xi_startino, &p32[i].xi_startino) ||
92 put_user(buffer[i].xi_alloccount, &p32[i].xi_alloccount) || 99 put_user(buffer[i].xi_alloccount, &p32[i].xi_alloccount) ||
93 put_user(buffer[i].xi_allocmask, &p32[i].xi_allocmask)) 100 put_user(buffer[i].xi_allocmask, &p32[i].xi_allocmask))
94 return -EFAULT; 101 return -XFS_ERROR(EFAULT);
95 } 102 }
96 *written = count * sizeof(*p32); 103 *written = count * sizeof(*p32);
97 return 0; 104 return 0;
@@ -103,24 +110,26 @@ STATIC int xfs_inumbers_fmt_compat(
103 110
104/* XFS_IOC_FSBULKSTAT and friends */ 111/* XFS_IOC_FSBULKSTAT and friends */
105 112
106STATIC int xfs_bstime_store_compat( 113STATIC int
107 compat_xfs_bstime_t __user *p32, 114xfs_bstime_store_compat(
108 const xfs_bstime_t *p) 115 compat_xfs_bstime_t __user *p32,
116 const xfs_bstime_t *p)
109{ 117{
110 __s32 sec32; 118 __s32 sec32;
111 119
112 sec32 = p->tv_sec; 120 sec32 = p->tv_sec;
113 if (put_user(sec32, &p32->tv_sec) || 121 if (put_user(sec32, &p32->tv_sec) ||
114 put_user(p->tv_nsec, &p32->tv_nsec)) 122 put_user(p->tv_nsec, &p32->tv_nsec))
115 return -EFAULT; 123 return -XFS_ERROR(EFAULT);
116 return 0; 124 return 0;
117} 125}
118 126
119STATIC int xfs_bulkstat_one_fmt_compat( 127STATIC int
128xfs_bulkstat_one_fmt_compat(
120 void __user *ubuffer, 129 void __user *ubuffer,
121 const xfs_bstat_t *buffer) 130 const xfs_bstat_t *buffer)
122{ 131{
123 compat_xfs_bstat_t __user *p32 = ubuffer; 132 compat_xfs_bstat_t __user *p32 = ubuffer;
124 133
125 if (put_user(buffer->bs_ino, &p32->bs_ino) || 134 if (put_user(buffer->bs_ino, &p32->bs_ino) ||
126 put_user(buffer->bs_mode, &p32->bs_mode) || 135 put_user(buffer->bs_mode, &p32->bs_mode) ||
@@ -142,7 +151,7 @@ STATIC int xfs_bulkstat_one_fmt_compat(
142 put_user(buffer->bs_dmevmask, &p32->bs_dmevmask) || 151 put_user(buffer->bs_dmevmask, &p32->bs_dmevmask) ||
143 put_user(buffer->bs_dmstate, &p32->bs_dmstate) || 152 put_user(buffer->bs_dmstate, &p32->bs_dmstate) ||
144 put_user(buffer->bs_aextents, &p32->bs_aextents)) 153 put_user(buffer->bs_aextents, &p32->bs_aextents))
145 return -EFAULT; 154 return -XFS_ERROR(EFAULT);
146 return sizeof(*p32); 155 return sizeof(*p32);
147} 156}
148 157
@@ -165,20 +174,20 @@ xfs_ioc_bulkstat_compat(
165 /* should be called again (unused here, but used in dmapi) */ 174 /* should be called again (unused here, but used in dmapi) */
166 175
167 if (!capable(CAP_SYS_ADMIN)) 176 if (!capable(CAP_SYS_ADMIN))
168 return -EPERM; 177 return -XFS_ERROR(EPERM);
169 178
170 if (XFS_FORCED_SHUTDOWN(mp)) 179 if (XFS_FORCED_SHUTDOWN(mp))
171 return -XFS_ERROR(EIO); 180 return -XFS_ERROR(EIO);
172 181
173 if (get_user(addr, &p32->lastip)) 182 if (get_user(addr, &p32->lastip))
174 return -EFAULT; 183 return -XFS_ERROR(EFAULT);
175 bulkreq.lastip = compat_ptr(addr); 184 bulkreq.lastip = compat_ptr(addr);
176 if (get_user(bulkreq.icount, &p32->icount) || 185 if (get_user(bulkreq.icount, &p32->icount) ||
177 get_user(addr, &p32->ubuffer)) 186 get_user(addr, &p32->ubuffer))
178 return -EFAULT; 187 return -XFS_ERROR(EFAULT);
179 bulkreq.ubuffer = compat_ptr(addr); 188 bulkreq.ubuffer = compat_ptr(addr);
180 if (get_user(addr, &p32->ocount)) 189 if (get_user(addr, &p32->ocount))
181 return -EFAULT; 190 return -XFS_ERROR(EFAULT);
182 bulkreq.ocount = compat_ptr(addr); 191 bulkreq.ocount = compat_ptr(addr);
183 192
184 if (copy_from_user(&inlast, bulkreq.lastip, sizeof(__s64))) 193 if (copy_from_user(&inlast, bulkreq.lastip, sizeof(__s64)))
@@ -216,38 +225,40 @@ xfs_ioc_bulkstat_compat(
216 return 0; 225 return 0;
217} 226}
218 227
219STATIC unsigned long xfs_ioctl32_fshandle(unsigned long arg) 228STATIC int
229xfs_compat_handlereq_copyin(
230 xfs_fsop_handlereq_t *hreq,
231 compat_xfs_fsop_handlereq_t __user *arg32)
220{ 232{
221 compat_xfs_fsop_handlereq_t __user *p32 = (void __user *)arg; 233 compat_xfs_fsop_handlereq_t hreq32;
222 xfs_fsop_handlereq_t __user *p = compat_alloc_user_space(sizeof(*p)); 234
223 u32 addr; 235 if (copy_from_user(&hreq32, arg32, sizeof(compat_xfs_fsop_handlereq_t)))
224 236 return -XFS_ERROR(EFAULT);
225 if (copy_in_user(&p->fd, &p32->fd, sizeof(__u32)) || 237
226 get_user(addr, &p32->path) || 238 hreq->fd = hreq32.fd;
227 put_user(compat_ptr(addr), &p->path) || 239 hreq->path = compat_ptr(hreq32.path);
228 copy_in_user(&p->oflags, &p32->oflags, sizeof(__u32)) || 240 hreq->oflags = hreq32.oflags;
229 get_user(addr, &p32->ihandle) || 241 hreq->ihandle = compat_ptr(hreq32.ihandle);
230 put_user(compat_ptr(addr), &p->ihandle) || 242 hreq->ihandlen = hreq32.ihandlen;
231 copy_in_user(&p->ihandlen, &p32->ihandlen, sizeof(__u32)) || 243 hreq->ohandle = compat_ptr(hreq32.ohandle);
232 get_user(addr, &p32->ohandle) || 244 hreq->ohandlen = compat_ptr(hreq32.ohandlen);
233 put_user(compat_ptr(addr), &p->ohandle) || 245
234 get_user(addr, &p32->ohandlen) || 246 return 0;
235 put_user(compat_ptr(addr), &p->ohandlen))
236 return -EFAULT;
237
238 return (unsigned long)p;
239} 247}
240 248
241STATIC long 249STATIC long
242xfs_compat_ioctl( 250xfs_compat_ioctl(
243 int mode, 251 xfs_inode_t *ip,
244 struct file *file, 252 struct file *filp,
253 int ioflags,
245 unsigned cmd, 254 unsigned cmd,
246 unsigned long arg) 255 void __user *arg)
247{ 256{
248 struct inode *inode = file->f_path.dentry->d_inode; 257 struct inode *inode = filp->f_path.dentry->d_inode;
258 xfs_mount_t *mp = ip->i_mount;
249 int error; 259 int error;
250 260
261 xfs_itrace_entry(XFS_I(inode));
251 switch (cmd) { 262 switch (cmd) {
252 case XFS_IOC_DIOINFO: 263 case XFS_IOC_DIOINFO:
253 case XFS_IOC_FSGEOMETRY: 264 case XFS_IOC_FSGEOMETRY:
@@ -290,14 +301,16 @@ xfs_compat_ioctl(
290 case XFS_IOC_RESVSP_32: 301 case XFS_IOC_RESVSP_32:
291 case XFS_IOC_UNRESVSP_32: 302 case XFS_IOC_UNRESVSP_32:
292 case XFS_IOC_RESVSP64_32: 303 case XFS_IOC_RESVSP64_32:
293 case XFS_IOC_UNRESVSP64_32: 304 case XFS_IOC_UNRESVSP64_32: {
294 arg = xfs_ioctl32_flock(arg); 305 struct xfs_flock64 bf;
306
307 if (xfs_compat_flock64_copyin(&bf, arg))
308 return -XFS_ERROR(EFAULT);
295 cmd = _NATIVE_IOC(cmd, struct xfs_flock64); 309 cmd = _NATIVE_IOC(cmd, struct xfs_flock64);
296 break; 310 return xfs_ioc_space(ip, inode, filp, ioflags, cmd, &bf);
311 }
297 case XFS_IOC_FSGEOMETRY_V1_32: 312 case XFS_IOC_FSGEOMETRY_V1_32:
298 arg = xfs_ioctl32_geom_v1(arg); 313 return xfs_compat_ioc_fsgeometry_v1(mp, arg);
299 cmd = _NATIVE_IOC(cmd, struct xfs_fsop_geom_v1);
300 break;
301#else /* These are handled fine if no alignment issues */ 314#else /* These are handled fine if no alignment issues */
302 case XFS_IOC_ALLOCSP: 315 case XFS_IOC_ALLOCSP:
303 case XFS_IOC_FREESP: 316 case XFS_IOC_FREESP:
@@ -323,35 +336,55 @@ xfs_compat_ioctl(
323 cmd, (void __user*)arg); 336 cmd, (void __user*)arg);
324 case XFS_IOC_FD_TO_HANDLE_32: 337 case XFS_IOC_FD_TO_HANDLE_32:
325 case XFS_IOC_PATH_TO_HANDLE_32: 338 case XFS_IOC_PATH_TO_HANDLE_32:
326 case XFS_IOC_PATH_TO_FSHANDLE_32: 339 case XFS_IOC_PATH_TO_FSHANDLE_32: {
327 case XFS_IOC_OPEN_BY_HANDLE_32: 340 struct xfs_fsop_handlereq hreq;
328 case XFS_IOC_READLINK_BY_HANDLE_32: 341
329 arg = xfs_ioctl32_fshandle(arg); 342 if (xfs_compat_handlereq_copyin(&hreq, arg))
343 return -XFS_ERROR(EFAULT);
330 cmd = _NATIVE_IOC(cmd, struct xfs_fsop_handlereq); 344 cmd = _NATIVE_IOC(cmd, struct xfs_fsop_handlereq);
331 break; 345 return xfs_find_handle(cmd, &hreq);
346 }
347 case XFS_IOC_OPEN_BY_HANDLE_32: {
348 struct xfs_fsop_handlereq hreq;
349
350 if (xfs_compat_handlereq_copyin(&hreq, arg))
351 return -XFS_ERROR(EFAULT);
352 return xfs_open_by_handle(mp, &hreq, filp, inode);
353 }
354 case XFS_IOC_READLINK_BY_HANDLE_32: {
355 struct xfs_fsop_handlereq hreq;
356
357 if (xfs_compat_handlereq_copyin(&hreq, arg))
358 return -XFS_ERROR(EFAULT);
359 return xfs_readlink_by_handle(mp, &hreq, inode);
360 }
332 default: 361 default:
333 return -ENOIOCTLCMD; 362 return -XFS_ERROR(ENOIOCTLCMD);
334 } 363 }
335 364
336 error = xfs_ioctl(XFS_I(inode), file, mode, cmd, (void __user *)arg); 365 error = xfs_ioctl(ip, filp, ioflags, cmd, arg);
337 xfs_iflags_set(XFS_I(inode), XFS_IMODIFIED);
338 return error; 366 return error;
339} 367}
340 368
341long 369long
342xfs_file_compat_ioctl( 370xfs_file_compat_ioctl(
343 struct file *file, 371 struct file *filp,
344 unsigned cmd, 372 unsigned int cmd,
345 unsigned long arg) 373 unsigned long p)
346{ 374{
347 return xfs_compat_ioctl(0, file, cmd, arg); 375 struct inode *inode = filp->f_path.dentry->d_inode;
376
377 return xfs_compat_ioctl(XFS_I(inode), filp, 0, cmd, (void __user *)p);
348} 378}
349 379
350long 380long
351xfs_file_compat_invis_ioctl( 381xfs_file_compat_invis_ioctl(
352 struct file *file, 382 struct file *filp,
353 unsigned cmd, 383 unsigned int cmd,
354 unsigned long arg) 384 unsigned long p)
355{ 385{
356 return xfs_compat_ioctl(IO_INVIS, file, cmd, arg); 386 struct inode *inode = filp->f_path.dentry->d_inode;
387
388 return xfs_compat_ioctl(XFS_I(inode), filp, IO_INVIS, cmd,
389 (void __user *)p);
357} 390}