aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel/sys_sparc32.c
diff options
context:
space:
mode:
authorSam Ravnborg <sam@ravnborg.org>2008-12-03 06:11:52 -0500
committerDavid S. Miller <davem@davemloft.net>2008-12-04 12:17:21 -0500
commita88b5ba8bd8ac18aad65ee6c6a254e2e74876db3 (patch)
treeeb3d0ffaf53c3f7ec6083752c2097cecd1cb892a /arch/sparc/kernel/sys_sparc32.c
parentd670bd4f803c8b646acd20f3ba21e65458293faf (diff)
sparc,sparc64: unify kernel/
o Move all files from sparc64/kernel/ to sparc/kernel - rename as appropriate o Update sparc/Makefile to the changes o Update sparc/kernel/Makefile to include the sparc64 files NOTE: This commit changes link order on sparc64! Link order had to change for either of sparc32 and sparc64. And assuming sparc64 see more testing than sparc32 change link order on sparc64 where issues will be caught faster. Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc/kernel/sys_sparc32.c')
-rw-r--r--arch/sparc/kernel/sys_sparc32.c682
1 files changed, 682 insertions, 0 deletions
diff --git a/arch/sparc/kernel/sys_sparc32.c b/arch/sparc/kernel/sys_sparc32.c
new file mode 100644
index 000000000000..e800503879e4
--- /dev/null
+++ b/arch/sparc/kernel/sys_sparc32.c
@@ -0,0 +1,682 @@
1/* sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
2 *
3 * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
4 * Copyright (C) 1997, 2007 David S. Miller (davem@davemloft.net)
5 *
6 * These routines maintain argument size conversion between 32bit and 64bit
7 * environment.
8 */
9
10#include <linux/kernel.h>
11#include <linux/sched.h>
12#include <linux/capability.h>
13#include <linux/fs.h>
14#include <linux/mm.h>
15#include <linux/file.h>
16#include <linux/signal.h>
17#include <linux/resource.h>
18#include <linux/times.h>
19#include <linux/utsname.h>
20#include <linux/smp.h>
21#include <linux/smp_lock.h>
22#include <linux/sem.h>
23#include <linux/msg.h>
24#include <linux/shm.h>
25#include <linux/slab.h>
26#include <linux/uio.h>
27#include <linux/nfs_fs.h>
28#include <linux/quota.h>
29#include <linux/module.h>
30#include <linux/sunrpc/svc.h>
31#include <linux/nfsd/nfsd.h>
32#include <linux/nfsd/cache.h>
33#include <linux/nfsd/xdr.h>
34#include <linux/nfsd/syscall.h>
35#include <linux/poll.h>
36#include <linux/personality.h>
37#include <linux/stat.h>
38#include <linux/filter.h>
39#include <linux/highmem.h>
40#include <linux/highuid.h>
41#include <linux/mman.h>
42#include <linux/ipv6.h>
43#include <linux/in.h>
44#include <linux/icmpv6.h>
45#include <linux/syscalls.h>
46#include <linux/sysctl.h>
47#include <linux/binfmts.h>
48#include <linux/dnotify.h>
49#include <linux/security.h>
50#include <linux/compat.h>
51#include <linux/vfs.h>
52#include <linux/netfilter_ipv4/ip_tables.h>
53#include <linux/ptrace.h>
54
55#include <asm/types.h>
56#include <asm/uaccess.h>
57#include <asm/fpumacro.h>
58#include <asm/mmu_context.h>
59#include <asm/compat_signal.h>
60
61#ifdef CONFIG_SYSVIPC
62asmlinkage long compat_sys_ipc(u32 call, u32 first, u32 second, u32 third, compat_uptr_t ptr, u32 fifth)
63{
64 int version;
65
66 version = call >> 16; /* hack for backward compatibility */
67 call &= 0xffff;
68
69 switch (call) {
70 case SEMTIMEDOP:
71 if (fifth)
72 /* sign extend semid */
73 return compat_sys_semtimedop((int)first,
74 compat_ptr(ptr), second,
75 compat_ptr(fifth));
76 /* else fall through for normal semop() */
77 case SEMOP:
78 /* struct sembuf is the same on 32 and 64bit :)) */
79 /* sign extend semid */
80 return sys_semtimedop((int)first, compat_ptr(ptr), second,
81 NULL);
82 case SEMGET:
83 /* sign extend key, nsems */
84 return sys_semget((int)first, (int)second, third);
85 case SEMCTL:
86 /* sign extend semid, semnum */
87 return compat_sys_semctl((int)first, (int)second, third,
88 compat_ptr(ptr));
89
90 case MSGSND:
91 /* sign extend msqid */
92 return compat_sys_msgsnd((int)first, (int)second, third,
93 compat_ptr(ptr));
94 case MSGRCV:
95 /* sign extend msqid, msgtyp */
96 return compat_sys_msgrcv((int)first, second, (int)fifth,
97 third, version, compat_ptr(ptr));
98 case MSGGET:
99 /* sign extend key */
100 return sys_msgget((int)first, second);
101 case MSGCTL:
102 /* sign extend msqid */
103 return compat_sys_msgctl((int)first, second, compat_ptr(ptr));
104
105 case SHMAT:
106 /* sign extend shmid */
107 return compat_sys_shmat((int)first, second, third, version,
108 compat_ptr(ptr));
109 case SHMDT:
110 return sys_shmdt(compat_ptr(ptr));
111 case SHMGET:
112 /* sign extend key_t */
113 return sys_shmget((int)first, second, third);
114 case SHMCTL:
115 /* sign extend shmid */
116 return compat_sys_shmctl((int)first, second, compat_ptr(ptr));
117
118 default:
119 return -ENOSYS;
120 };
121
122 return -ENOSYS;
123}
124#endif
125
126asmlinkage long sys32_truncate64(const char __user * path, unsigned long high, unsigned long low)
127{
128 if ((int)high < 0)
129 return -EINVAL;
130 else
131 return sys_truncate(path, (high << 32) | low);
132}
133
134asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned long low)
135{
136 if ((int)high < 0)
137 return -EINVAL;
138 else
139 return sys_ftruncate(fd, (high << 32) | low);
140}
141
142static int cp_compat_stat64(struct kstat *stat,
143 struct compat_stat64 __user *statbuf)
144{
145 int err;
146
147 err = put_user(huge_encode_dev(stat->dev), &statbuf->st_dev);
148 err |= put_user(stat->ino, &statbuf->st_ino);
149 err |= put_user(stat->mode, &statbuf->st_mode);
150 err |= put_user(stat->nlink, &statbuf->st_nlink);
151 err |= put_user(stat->uid, &statbuf->st_uid);
152 err |= put_user(stat->gid, &statbuf->st_gid);
153 err |= put_user(huge_encode_dev(stat->rdev), &statbuf->st_rdev);
154 err |= put_user(0, (unsigned long __user *) &statbuf->__pad3[0]);
155 err |= put_user(stat->size, &statbuf->st_size);
156 err |= put_user(stat->blksize, &statbuf->st_blksize);
157 err |= put_user(0, (unsigned int __user *) &statbuf->__pad4[0]);
158 err |= put_user(0, (unsigned int __user *) &statbuf->__pad4[4]);
159 err |= put_user(stat->blocks, &statbuf->st_blocks);
160 err |= put_user(stat->atime.tv_sec, &statbuf->st_atime);
161 err |= put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec);
162 err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime);
163 err |= put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec);
164 err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime);
165 err |= put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec);
166 err |= put_user(0, &statbuf->__unused4);
167 err |= put_user(0, &statbuf->__unused5);
168
169 return err;
170}
171
172asmlinkage long compat_sys_stat64(char __user * filename,
173 struct compat_stat64 __user *statbuf)
174{
175 struct kstat stat;
176 int error = vfs_stat(filename, &stat);
177
178 if (!error)
179 error = cp_compat_stat64(&stat, statbuf);
180 return error;
181}
182
183asmlinkage long compat_sys_lstat64(char __user * filename,
184 struct compat_stat64 __user *statbuf)
185{
186 struct kstat stat;
187 int error = vfs_lstat(filename, &stat);
188
189 if (!error)
190 error = cp_compat_stat64(&stat, statbuf);
191 return error;
192}
193
194asmlinkage long compat_sys_fstat64(unsigned int fd,
195 struct compat_stat64 __user * statbuf)
196{
197 struct kstat stat;
198 int error = vfs_fstat(fd, &stat);
199
200 if (!error)
201 error = cp_compat_stat64(&stat, statbuf);
202 return error;
203}
204
205asmlinkage long compat_sys_fstatat64(unsigned int dfd, char __user *filename,
206 struct compat_stat64 __user * statbuf, int flag)
207{
208 struct kstat stat;
209 int error = -EINVAL;
210
211 if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
212 goto out;
213
214 if (flag & AT_SYMLINK_NOFOLLOW)
215 error = vfs_lstat_fd(dfd, filename, &stat);
216 else
217 error = vfs_stat_fd(dfd, filename, &stat);
218
219 if (!error)
220 error = cp_compat_stat64(&stat, statbuf);
221
222out:
223 return error;
224}
225
226asmlinkage long compat_sys_sysfs(int option, u32 arg1, u32 arg2)
227{
228 return sys_sysfs(option, arg1, arg2);
229}
230
231asmlinkage long compat_sys_sched_rr_get_interval(compat_pid_t pid, struct compat_timespec __user *interval)
232{
233 struct timespec t;
234 int ret;
235 mm_segment_t old_fs = get_fs ();
236
237 set_fs (KERNEL_DS);
238 ret = sys_sched_rr_get_interval(pid, (struct timespec __user *) &t);
239 set_fs (old_fs);
240 if (put_compat_timespec(&t, interval))
241 return -EFAULT;
242 return ret;
243}
244
245asmlinkage long compat_sys_rt_sigprocmask(int how,
246 compat_sigset_t __user *set,
247 compat_sigset_t __user *oset,
248 compat_size_t sigsetsize)
249{
250 sigset_t s;
251 compat_sigset_t s32;
252 int ret;
253 mm_segment_t old_fs = get_fs();
254
255 if (set) {
256 if (copy_from_user (&s32, set, sizeof(compat_sigset_t)))
257 return -EFAULT;
258 switch (_NSIG_WORDS) {
259 case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);
260 case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32);
261 case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32);
262 case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
263 }
264 }
265 set_fs (KERNEL_DS);
266 ret = sys_rt_sigprocmask(how,
267 set ? (sigset_t __user *) &s : NULL,
268 oset ? (sigset_t __user *) &s : NULL,
269 sigsetsize);
270 set_fs (old_fs);
271 if (ret) return ret;
272 if (oset) {
273 switch (_NSIG_WORDS) {
274 case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
275 case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
276 case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
277 case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
278 }
279 if (copy_to_user (oset, &s32, sizeof(compat_sigset_t)))
280 return -EFAULT;
281 }
282 return 0;
283}
284
285asmlinkage long sys32_rt_sigpending(compat_sigset_t __user *set,
286 compat_size_t sigsetsize)
287{
288 sigset_t s;
289 compat_sigset_t s32;
290 int ret;
291 mm_segment_t old_fs = get_fs();
292
293 set_fs (KERNEL_DS);
294 ret = sys_rt_sigpending((sigset_t __user *) &s, sigsetsize);
295 set_fs (old_fs);
296 if (!ret) {
297 switch (_NSIG_WORDS) {
298 case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
299 case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
300 case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
301 case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
302 }
303 if (copy_to_user (set, &s32, sizeof(compat_sigset_t)))
304 return -EFAULT;
305 }
306 return ret;
307}
308
309asmlinkage long compat_sys_rt_sigqueueinfo(int pid, int sig,
310 struct compat_siginfo __user *uinfo)
311{
312 siginfo_t info;
313 int ret;
314 mm_segment_t old_fs = get_fs();
315
316 if (copy_siginfo_from_user32(&info, uinfo))
317 return -EFAULT;
318
319 set_fs (KERNEL_DS);
320 ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *) &info);
321 set_fs (old_fs);
322 return ret;
323}
324
325asmlinkage long compat_sys_sigaction(int sig, struct old_sigaction32 __user *act,
326 struct old_sigaction32 __user *oact)
327{
328 struct k_sigaction new_ka, old_ka;
329 int ret;
330
331 WARN_ON_ONCE(sig >= 0);
332 sig = -sig;
333
334 if (act) {
335 compat_old_sigset_t mask;
336 u32 u_handler, u_restorer;
337
338 ret = get_user(u_handler, &act->sa_handler);
339 new_ka.sa.sa_handler = compat_ptr(u_handler);
340 ret |= __get_user(u_restorer, &act->sa_restorer);
341 new_ka.sa.sa_restorer = compat_ptr(u_restorer);
342 ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
343 ret |= __get_user(mask, &act->sa_mask);
344 if (ret)
345 return ret;
346 new_ka.ka_restorer = NULL;
347 siginitset(&new_ka.sa.sa_mask, mask);
348 }
349
350 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
351
352 if (!ret && oact) {
353 ret = put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler);
354 ret |= __put_user(ptr_to_compat(old_ka.sa.sa_restorer), &oact->sa_restorer);
355 ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
356 ret |= __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
357 }
358
359 return ret;
360}
361
362asmlinkage long compat_sys_rt_sigaction(int sig,
363 struct sigaction32 __user *act,
364 struct sigaction32 __user *oact,
365 void __user *restorer,
366 compat_size_t sigsetsize)
367{
368 struct k_sigaction new_ka, old_ka;
369 int ret;
370 compat_sigset_t set32;
371
372 /* XXX: Don't preclude handling different sized sigset_t's. */
373 if (sigsetsize != sizeof(compat_sigset_t))
374 return -EINVAL;
375
376 if (act) {
377 u32 u_handler, u_restorer;
378
379 new_ka.ka_restorer = restorer;
380 ret = get_user(u_handler, &act->sa_handler);
381 new_ka.sa.sa_handler = compat_ptr(u_handler);
382 ret |= __copy_from_user(&set32, &act->sa_mask, sizeof(compat_sigset_t));
383 switch (_NSIG_WORDS) {
384 case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6] | (((long)set32.sig[7]) << 32);
385 case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4] | (((long)set32.sig[5]) << 32);
386 case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2] | (((long)set32.sig[3]) << 32);
387 case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0] | (((long)set32.sig[1]) << 32);
388 }
389 ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
390 ret |= __get_user(u_restorer, &act->sa_restorer);
391 new_ka.sa.sa_restorer = compat_ptr(u_restorer);
392 if (ret)
393 return -EFAULT;
394 }
395
396 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
397
398 if (!ret && oact) {
399 switch (_NSIG_WORDS) {
400 case 4: set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32); set32.sig[6] = old_ka.sa.sa_mask.sig[3];
401 case 3: set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32); set32.sig[4] = old_ka.sa.sa_mask.sig[2];
402 case 2: set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32); set32.sig[2] = old_ka.sa.sa_mask.sig[1];
403 case 1: set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32); set32.sig[0] = old_ka.sa.sa_mask.sig[0];
404 }
405 ret = put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler);
406 ret |= __copy_to_user(&oact->sa_mask, &set32, sizeof(compat_sigset_t));
407 ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
408 ret |= __put_user(ptr_to_compat(old_ka.sa.sa_restorer), &oact->sa_restorer);
409 if (ret)
410 ret = -EFAULT;
411 }
412
413 return ret;
414}
415
416/*
417 * sparc32_execve() executes a new program after the asm stub has set
418 * things up for us. This should basically do what I want it to.
419 */
420asmlinkage long sparc32_execve(struct pt_regs *regs)
421{
422 int error, base = 0;
423 char *filename;
424
425 /* User register window flush is done by entry.S */
426
427 /* Check for indirect call. */
428 if ((u32)regs->u_regs[UREG_G1] == 0)
429 base = 1;
430
431 filename = getname(compat_ptr(regs->u_regs[base + UREG_I0]));
432 error = PTR_ERR(filename);
433 if (IS_ERR(filename))
434 goto out;
435
436 error = compat_do_execve(filename,
437 compat_ptr(regs->u_regs[base + UREG_I1]),
438 compat_ptr(regs->u_regs[base + UREG_I2]), regs);
439
440 putname(filename);
441
442 if (!error) {
443 fprs_write(0);
444 current_thread_info()->xfsr[0] = 0;
445 current_thread_info()->fpsaved[0] = 0;
446 regs->tstate &= ~TSTATE_PEF;
447 }
448out:
449 return error;
450}
451
452#ifdef CONFIG_MODULES
453
454asmlinkage long sys32_init_module(void __user *umod, u32 len,
455 const char __user *uargs)
456{
457 return sys_init_module(umod, len, uargs);
458}
459
460asmlinkage long sys32_delete_module(const char __user *name_user,
461 unsigned int flags)
462{
463 return sys_delete_module(name_user, flags);
464}
465
466#else /* CONFIG_MODULES */
467
468asmlinkage long sys32_init_module(const char __user *name_user,
469 struct module __user *mod_user)
470{
471 return -ENOSYS;
472}
473
474asmlinkage long sys32_delete_module(const char __user *name_user)
475{
476 return -ENOSYS;
477}
478
479#endif /* CONFIG_MODULES */
480
481asmlinkage compat_ssize_t sys32_pread64(unsigned int fd,
482 char __user *ubuf,
483 compat_size_t count,
484 unsigned long poshi,
485 unsigned long poslo)
486{
487 return sys_pread64(fd, ubuf, count, (poshi << 32) | poslo);
488}
489
490asmlinkage compat_ssize_t sys32_pwrite64(unsigned int fd,
491 char __user *ubuf,
492 compat_size_t count,
493 unsigned long poshi,
494 unsigned long poslo)
495{
496 return sys_pwrite64(fd, ubuf, count, (poshi << 32) | poslo);
497}
498
499asmlinkage long compat_sys_readahead(int fd,
500 unsigned long offhi,
501 unsigned long offlo,
502 compat_size_t count)
503{
504 return sys_readahead(fd, (offhi << 32) | offlo, count);
505}
506
507long compat_sys_fadvise64(int fd,
508 unsigned long offhi,
509 unsigned long offlo,
510 compat_size_t len, int advice)
511{
512 return sys_fadvise64_64(fd, (offhi << 32) | offlo, len, advice);
513}
514
515long compat_sys_fadvise64_64(int fd,
516 unsigned long offhi, unsigned long offlo,
517 unsigned long lenhi, unsigned long lenlo,
518 int advice)
519{
520 return sys_fadvise64_64(fd,
521 (offhi << 32) | offlo,
522 (lenhi << 32) | lenlo,
523 advice);
524}
525
526asmlinkage long compat_sys_sendfile(int out_fd, int in_fd,
527 compat_off_t __user *offset,
528 compat_size_t count)
529{
530 mm_segment_t old_fs = get_fs();
531 int ret;
532 off_t of;
533
534 if (offset && get_user(of, offset))
535 return -EFAULT;
536
537 set_fs(KERNEL_DS);
538 ret = sys_sendfile(out_fd, in_fd,
539 offset ? (off_t __user *) &of : NULL,
540 count);
541 set_fs(old_fs);
542
543 if (offset && put_user(of, offset))
544 return -EFAULT;
545
546 return ret;
547}
548
549asmlinkage long compat_sys_sendfile64(int out_fd, int in_fd,
550 compat_loff_t __user *offset,
551 compat_size_t count)
552{
553 mm_segment_t old_fs = get_fs();
554 int ret;
555 loff_t lof;
556
557 if (offset && get_user(lof, offset))
558 return -EFAULT;
559
560 set_fs(KERNEL_DS);
561 ret = sys_sendfile64(out_fd, in_fd,
562 offset ? (loff_t __user *) &lof : NULL,
563 count);
564 set_fs(old_fs);
565
566 if (offset && put_user(lof, offset))
567 return -EFAULT;
568
569 return ret;
570}
571
572/* This is just a version for 32-bit applications which does
573 * not force O_LARGEFILE on.
574 */
575
576asmlinkage long sparc32_open(const char __user *filename,
577 int flags, int mode)
578{
579 return do_sys_open(AT_FDCWD, filename, flags, mode);
580}
581
582extern unsigned long do_mremap(unsigned long addr,
583 unsigned long old_len, unsigned long new_len,
584 unsigned long flags, unsigned long new_addr);
585
586asmlinkage unsigned long sys32_mremap(unsigned long addr,
587 unsigned long old_len, unsigned long new_len,
588 unsigned long flags, u32 __new_addr)
589{
590 unsigned long ret = -EINVAL;
591 unsigned long new_addr = __new_addr;
592
593 if (unlikely(sparc_mmap_check(addr, old_len)))
594 goto out;
595 if (unlikely(sparc_mmap_check(new_addr, new_len)))
596 goto out;
597 down_write(&current->mm->mmap_sem);
598 ret = do_mremap(addr, old_len, new_len, flags, new_addr);
599 up_write(&current->mm->mmap_sem);
600out:
601 return ret;
602}
603
604struct __sysctl_args32 {
605 u32 name;
606 int nlen;
607 u32 oldval;
608 u32 oldlenp;
609 u32 newval;
610 u32 newlen;
611 u32 __unused[4];
612};
613
614asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
615{
616#ifndef CONFIG_SYSCTL_SYSCALL
617 return -ENOSYS;
618#else
619 struct __sysctl_args32 tmp;
620 int error;
621 size_t oldlen, __user *oldlenp = NULL;
622 unsigned long addr = (((unsigned long)&args->__unused[0]) + 7UL) & ~7UL;
623
624 if (copy_from_user(&tmp, args, sizeof(tmp)))
625 return -EFAULT;
626
627 if (tmp.oldval && tmp.oldlenp) {
628 /* Duh, this is ugly and might not work if sysctl_args
629 is in read-only memory, but do_sysctl does indirectly
630 a lot of uaccess in both directions and we'd have to
631 basically copy the whole sysctl.c here, and
632 glibc's __sysctl uses rw memory for the structure
633 anyway. */
634 if (get_user(oldlen, (u32 __user *)(unsigned long)tmp.oldlenp) ||
635 put_user(oldlen, (size_t __user *)addr))
636 return -EFAULT;
637 oldlenp = (size_t __user *)addr;
638 }
639
640 lock_kernel();
641 error = do_sysctl((int __user *)(unsigned long) tmp.name,
642 tmp.nlen,
643 (void __user *)(unsigned long) tmp.oldval,
644 oldlenp,
645 (void __user *)(unsigned long) tmp.newval,
646 tmp.newlen);
647 unlock_kernel();
648 if (oldlenp) {
649 if (!error) {
650 if (get_user(oldlen, (size_t __user *)addr) ||
651 put_user(oldlen, (u32 __user *)(unsigned long) tmp.oldlenp))
652 error = -EFAULT;
653 }
654 if (copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused)))
655 error = -EFAULT;
656 }
657 return error;
658#endif
659}
660
661long sys32_lookup_dcookie(unsigned long cookie_high,
662 unsigned long cookie_low,
663 char __user *buf, size_t len)
664{
665 return sys_lookup_dcookie((cookie_high << 32) | cookie_low,
666 buf, len);
667}
668
669long compat_sync_file_range(int fd, unsigned long off_high, unsigned long off_low, unsigned long nb_high, unsigned long nb_low, int flags)
670{
671 return sys_sync_file_range(fd,
672 (off_high << 32) | off_low,
673 (nb_high << 32) | nb_low,
674 flags);
675}
676
677asmlinkage long compat_sys_fallocate(int fd, int mode, u32 offhi, u32 offlo,
678 u32 lenhi, u32 lenlo)
679{
680 return sys_fallocate(fd, mode, ((loff_t)offhi << 32) | offlo,
681 ((loff_t)lenhi << 32) | lenlo);
682}