OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [sparc64/] [kernel/] [sys_sparc32.c] - Blame information for rev 1275

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* $Id: sys_sparc32.c,v 1.1.1.1 2004-04-15 01:34:49 phoenix Exp $
2
 * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
3
 *
4
 * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
5
 * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
6
 *
7
 * These routines maintain argument size conversion between 32bit and 64bit
8
 * environment.
9
 */
10
 
11
#include <linux/config.h>
12
#include <linux/kernel.h>
13
#include <linux/sched.h>
14
#include <linux/fs.h> 
15
#include <linux/mm.h> 
16
#include <linux/file.h> 
17
#include <linux/signal.h>
18
#include <linux/utime.h>
19
#include <linux/resource.h>
20
#include <linux/times.h>
21
#include <linux/utsname.h>
22
#include <linux/timex.h>
23
#include <linux/smp.h>
24
#include <linux/smp_lock.h>
25
#include <linux/sem.h>
26
#include <linux/msg.h>
27
#include <linux/shm.h>
28
#include <linux/slab.h>
29
#include <linux/uio.h>
30
#include <linux/nfs_fs.h>
31
#include <linux/smb_fs.h>
32
#include <linux/smb_mount.h>
33
#include <linux/ncp_fs.h>
34
#include <linux/quota.h>
35
#include <linux/quotacompat.h>
36
#include <linux/module.h>
37
#include <linux/sunrpc/svc.h>
38
#include <linux/nfsd/nfsd.h>
39
#include <linux/nfsd/cache.h>
40
#include <linux/nfsd/xdr.h>
41
#include <linux/nfsd/syscall.h>
42
#include <linux/poll.h>
43
#include <linux/personality.h>
44
#include <linux/stat.h>
45
#include <linux/filter.h>
46
#include <linux/highmem.h>
47
#include <linux/highuid.h>
48
#include <linux/mman.h>
49
#include <linux/ipv6.h>
50
#include <linux/in.h>
51
#include <linux/icmpv6.h>
52
#include <linux/sysctl.h>
53
#include <linux/dnotify.h>
54
#include <linux/netfilter_ipv4/ip_tables.h>
55
 
56
#include <asm/types.h>
57
#include <asm/ipc.h>
58
#include <asm/uaccess.h>
59
#include <asm/fpumacro.h>
60
#include <asm/semaphore.h>
61
 
62
#include <net/scm.h>
63
 
64
/* Use this to get at 32-bit user passed pointers. */
65
/* Things to consider: the low-level assembly stub does
66
   srl x, 0, x for first four arguments, so if you have
67
   pointer to something in the first four arguments, just
68
   declare it as a pointer, not u32. On the other side,
69
   arguments from 5th onwards should be declared as u32
70
   for pointers, and need AA() around each usage.
71
   A() macro should be used for places where you e.g.
72
   have some internal variable u32 and just want to get
73
   rid of a compiler warning. AA() has to be used in
74
   places where you want to convert a function argument
75
   to 32bit pointer or when you e.g. access pt_regs
76
   structure and want to consider 32bit registers only.
77
   -jj
78
 */
79
#define A(__x) ((unsigned long)(__x))
80
#define AA(__x)                         \
81
({      unsigned long __ret;            \
82
        __asm__ ("srl   %0, 0, %0"      \
83
                 : "=r" (__ret)         \
84
                 : "0" (__x));           \
85
        __ret;                          \
86
})
87
 
88
extern asmlinkage long sys_chown(const char *, uid_t,gid_t);
89
extern asmlinkage long sys_lchown(const char *, uid_t,gid_t);
90
extern asmlinkage long sys_fchown(unsigned int, uid_t,gid_t);
91
extern asmlinkage long sys_setregid(gid_t, gid_t);
92
extern asmlinkage long sys_setgid(gid_t);
93
extern asmlinkage long sys_setreuid(uid_t, uid_t);
94
extern asmlinkage long sys_setuid(uid_t);
95
extern asmlinkage long sys_setresuid(uid_t, uid_t, uid_t);
96
extern asmlinkage long sys_setresgid(gid_t, gid_t, gid_t);
97
extern asmlinkage long sys_setfsuid(uid_t);
98
extern asmlinkage long sys_setfsgid(gid_t);
99
 
100
/* For this source file, we want overflow handling. */
101
 
102
#undef high2lowuid
103
#undef high2lowgid
104
#undef low2highuid
105
#undef low2highgid
106
#undef SET_UID16
107
#undef SET_GID16
108
#undef NEW_TO_OLD_UID
109
#undef NEW_TO_OLD_GID
110
#undef SET_OLDSTAT_UID
111
#undef SET_OLDSTAT_GID
112
#undef SET_STAT_UID
113
#undef SET_STAT_GID
114
 
115
#define high2lowuid(uid) ((uid) > 65535) ? (u16)overflowuid : (u16)(uid)
116
#define high2lowgid(gid) ((gid) > 65535) ? (u16)overflowgid : (u16)(gid)
117
#define low2highuid(uid) ((uid) == (u16)-1) ? (uid_t)-1 : (uid_t)(uid)
118
#define low2highgid(gid) ((gid) == (u16)-1) ? (gid_t)-1 : (gid_t)(gid)
119
#define SET_UID16(var, uid)     var = high2lowuid(uid)
120
#define SET_GID16(var, gid)     var = high2lowgid(gid)
121
#define NEW_TO_OLD_UID(uid)     high2lowuid(uid)
122
#define NEW_TO_OLD_GID(gid)     high2lowgid(gid)
123
#define SET_OLDSTAT_UID(stat, uid)      (stat).st_uid = high2lowuid(uid)
124
#define SET_OLDSTAT_GID(stat, gid)      (stat).st_gid = high2lowgid(gid)
125
#define SET_STAT_UID(stat, uid)         (stat).st_uid = high2lowuid(uid)
126
#define SET_STAT_GID(stat, gid)         (stat).st_gid = high2lowgid(gid)
127
 
128
asmlinkage long sys32_chown16(const char * filename, u16 user, u16 group)
129
{
130
        return sys_chown(filename, low2highuid(user), low2highgid(group));
131
}
132
 
133
asmlinkage long sys32_lchown16(const char * filename, u16 user, u16 group)
134
{
135
        return sys_lchown(filename, low2highuid(user), low2highgid(group));
136
}
137
 
138
asmlinkage long sys32_fchown16(unsigned int fd, u16 user, u16 group)
139
{
140
        return sys_fchown(fd, low2highuid(user), low2highgid(group));
141
}
142
 
143
asmlinkage long sys32_setregid16(u16 rgid, u16 egid)
144
{
145
        return sys_setregid(low2highgid(rgid), low2highgid(egid));
146
}
147
 
148
asmlinkage long sys32_setgid16(u16 gid)
149
{
150
        return sys_setgid((gid_t)gid);
151
}
152
 
153
asmlinkage long sys32_setreuid16(u16 ruid, u16 euid)
154
{
155
        return sys_setreuid(low2highuid(ruid), low2highuid(euid));
156
}
157
 
158
asmlinkage long sys32_setuid16(u16 uid)
159
{
160
        return sys_setuid((uid_t)uid);
161
}
162
 
163
asmlinkage long sys32_setresuid16(u16 ruid, u16 euid, u16 suid)
164
{
165
        return sys_setresuid(low2highuid(ruid), low2highuid(euid),
166
                low2highuid(suid));
167
}
168
 
169
asmlinkage long sys32_getresuid16(u16 *ruid, u16 *euid, u16 *suid)
170
{
171
        int retval;
172
 
173
        if (!(retval = put_user(high2lowuid(current->uid), ruid)) &&
174
            !(retval = put_user(high2lowuid(current->euid), euid)))
175
                retval = put_user(high2lowuid(current->suid), suid);
176
 
177
        return retval;
178
}
179
 
180
asmlinkage long sys32_setresgid16(u16 rgid, u16 egid, u16 sgid)
181
{
182
        return sys_setresgid(low2highgid(rgid), low2highgid(egid),
183
                low2highgid(sgid));
184
}
185
 
186
asmlinkage long sys32_getresgid16(u16 *rgid, u16 *egid, u16 *sgid)
187
{
188
        int retval;
189
 
190
        if (!(retval = put_user(high2lowgid(current->gid), rgid)) &&
191
            !(retval = put_user(high2lowgid(current->egid), egid)))
192
                retval = put_user(high2lowgid(current->sgid), sgid);
193
 
194
        return retval;
195
}
196
 
197
asmlinkage long sys32_setfsuid16(u16 uid)
198
{
199
        return sys_setfsuid((uid_t)uid);
200
}
201
 
202
asmlinkage long sys32_setfsgid16(u16 gid)
203
{
204
        return sys_setfsgid((gid_t)gid);
205
}
206
 
207
asmlinkage long sys32_getgroups16(int gidsetsize, u16 *grouplist)
208
{
209
        u16 groups[NGROUPS];
210
        int i,j;
211
 
212
        if (gidsetsize < 0)
213
                return -EINVAL;
214
        i = current->ngroups;
215
        if (gidsetsize) {
216
                if (i > gidsetsize)
217
                        return -EINVAL;
218
                for(j=0;j<i;j++)
219
                        groups[j] = current->groups[j];
220
                if (copy_to_user(grouplist, groups, sizeof(u16)*i))
221
                        return -EFAULT;
222
        }
223
        return i;
224
}
225
 
226
asmlinkage long sys32_setgroups16(int gidsetsize, u16 *grouplist)
227
{
228
        u16 groups[NGROUPS];
229
        int i;
230
 
231
        if (!capable(CAP_SETGID))
232
                return -EPERM;
233
        if ((unsigned) gidsetsize > NGROUPS)
234
                return -EINVAL;
235
        if (copy_from_user(groups, grouplist, gidsetsize * sizeof(u16)))
236
                return -EFAULT;
237
        for (i = 0 ; i < gidsetsize ; i++)
238
                current->groups[i] = (gid_t)groups[i];
239
        current->ngroups = gidsetsize;
240
        return 0;
241
}
242
 
243
asmlinkage long sys32_getuid16(void)
244
{
245
        return high2lowuid(current->uid);
246
}
247
 
248
asmlinkage long sys32_geteuid16(void)
249
{
250
        return high2lowuid(current->euid);
251
}
252
 
253
asmlinkage long sys32_getgid16(void)
254
{
255
        return high2lowgid(current->gid);
256
}
257
 
258
asmlinkage long sys32_getegid16(void)
259
{
260
        return high2lowgid(current->egid);
261
}
262
 
263
/* 32-bit timeval and related flotsam.  */
264
 
265
struct timeval32
266
{
267
    int tv_sec, tv_usec;
268
};
269
 
270
struct itimerval32
271
{
272
    struct timeval32 it_interval;
273
    struct timeval32 it_value;
274
};
275
 
276
static inline long get_tv32(struct timeval *o, struct timeval32 *i)
277
{
278
        return (!access_ok(VERIFY_READ, tv32, sizeof(*tv32)) ||
279
                (__get_user(o->tv_sec, &i->tv_sec) |
280
                 __get_user(o->tv_usec, &i->tv_usec)));
281
}
282
 
283
static inline long put_tv32(struct timeval32 *o, struct timeval *i)
284
{
285
        return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
286
                (__put_user(i->tv_sec, &o->tv_sec) |
287
                 __put_user(i->tv_usec, &o->tv_usec)));
288
}
289
 
290
static inline long get_it32(struct itimerval *o, struct itimerval32 *i)
291
{
292
        return (!access_ok(VERIFY_READ, i32, sizeof(*i32)) ||
293
                (__get_user(o->it_interval.tv_sec, &i->it_interval.tv_sec) |
294
                 __get_user(o->it_interval.tv_usec, &i->it_interval.tv_usec) |
295
                 __get_user(o->it_value.tv_sec, &i->it_value.tv_sec) |
296
                 __get_user(o->it_value.tv_usec, &i->it_value.tv_usec)));
297
}
298
 
299
static inline long put_it32(struct itimerval32 *o, struct itimerval *i)
300
{
301
        return (!access_ok(VERIFY_WRITE, i32, sizeof(*i32)) ||
302
                (__put_user(i->it_interval.tv_sec, &o->it_interval.tv_sec) |
303
                 __put_user(i->it_interval.tv_usec, &o->it_interval.tv_usec) |
304
                 __put_user(i->it_value.tv_sec, &o->it_value.tv_sec) |
305
                 __put_user(i->it_value.tv_usec, &o->it_value.tv_usec)));
306
}
307
 
308
extern asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on);
309
 
310
asmlinkage int sys32_ioperm(u32 from, u32 num, int on)
311
{
312
        return sys_ioperm((unsigned long)from, (unsigned long)num, on);
313
}
314
 
315
struct msgbuf32 { s32 mtype; char mtext[1]; };
316
 
317
struct ipc_perm32
318
{
319
        key_t             key;
320
        __kernel_uid_t32  uid;
321
        __kernel_gid_t32  gid;
322
        __kernel_uid_t32  cuid;
323
        __kernel_gid_t32  cgid;
324
        __kernel_mode_t32 mode;
325
        unsigned short  seq;
326
};
327
 
328
struct semid_ds32 {
329
        struct ipc_perm32 sem_perm;               /* permissions .. see ipc.h */
330
        __kernel_time_t32 sem_otime;              /* last semop time */
331
        __kernel_time_t32 sem_ctime;              /* last change time */
332
        u32 sem_base;              /* ptr to first semaphore in array */
333
        u32 sem_pending;          /* pending operations to be processed */
334
        u32 sem_pending_last;    /* last pending operation */
335
        u32 undo;                  /* undo requests on this array */
336
        unsigned short  sem_nsems;              /* no. of semaphores in array */
337
};
338
 
339
struct semid64_ds32 {
340
        struct ipc64_perm sem_perm;               /* this structure is the same on sparc32 and sparc64 */
341
        unsigned int      __pad1;
342
        __kernel_time_t32 sem_otime;
343
        unsigned int      __pad2;
344
        __kernel_time_t32 sem_ctime;
345
        u32 sem_nsems;
346
        u32 __unused1;
347
        u32 __unused2;
348
};
349
 
350
struct msqid_ds32
351
{
352
        struct ipc_perm32 msg_perm;
353
        u32 msg_first;
354
        u32 msg_last;
355
        __kernel_time_t32 msg_stime;
356
        __kernel_time_t32 msg_rtime;
357
        __kernel_time_t32 msg_ctime;
358
        u32 wwait;
359
        u32 rwait;
360
        unsigned short msg_cbytes;
361
        unsigned short msg_qnum;
362
        unsigned short msg_qbytes;
363
        __kernel_ipc_pid_t32 msg_lspid;
364
        __kernel_ipc_pid_t32 msg_lrpid;
365
};
366
 
367
struct msqid64_ds32 {
368
        struct ipc64_perm msg_perm;
369
        unsigned int   __pad1;
370
        __kernel_time_t32 msg_stime;
371
        unsigned int   __pad2;
372
        __kernel_time_t32 msg_rtime;
373
        unsigned int   __pad3;
374
        __kernel_time_t32 msg_ctime;
375
        unsigned int  msg_cbytes;
376
        unsigned int  msg_qnum;
377
        unsigned int  msg_qbytes;
378
        __kernel_pid_t32 msg_lspid;
379
        __kernel_pid_t32 msg_lrpid;
380
        unsigned int  __unused1;
381
        unsigned int  __unused2;
382
};
383
 
384
 
385
struct shmid_ds32 {
386
        struct ipc_perm32       shm_perm;
387
        int                     shm_segsz;
388
        __kernel_time_t32       shm_atime;
389
        __kernel_time_t32       shm_dtime;
390
        __kernel_time_t32       shm_ctime;
391
        __kernel_ipc_pid_t32    shm_cpid;
392
        __kernel_ipc_pid_t32    shm_lpid;
393
        unsigned short          shm_nattch;
394
};
395
 
396
struct shmid64_ds32 {
397
        struct ipc64_perm       shm_perm;
398
        unsigned int            __pad1;
399
        __kernel_time_t32       shm_atime;
400
        unsigned int            __pad2;
401
        __kernel_time_t32       shm_dtime;
402
        unsigned int            __pad3;
403
        __kernel_time_t32       shm_ctime;
404
        __kernel_size_t32       shm_segsz;
405
        __kernel_pid_t32        shm_cpid;
406
        __kernel_pid_t32        shm_lpid;
407
        unsigned int            shm_nattch;
408
        unsigned int            __unused1;
409
        unsigned int            __unused2;
410
};
411
 
412
 
413
/*
414
 * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation..
415
 *
416
 * This is really horribly ugly.
417
 */
418
#define IPCOP_MASK(__x) (1UL << ((__x)&~IPC_64))
419
static int do_sys32_semctl(int first, int second, int third, void *uptr)
420
{
421
        union semun fourth;
422
        u32 pad;
423
        int err = -EINVAL;
424
 
425
        if (!uptr)
426
                goto out;
427
        err = -EFAULT;
428
        if (get_user (pad, (u32 *)uptr))
429
                goto out;
430
        if ((third & ~IPC_64) == SETVAL)
431
                fourth.val = (int)pad;
432
        else
433
                fourth.__pad = (void *)A(pad);
434
        if (IPCOP_MASK (third) &
435
            (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (SEM_INFO) | IPCOP_MASK (GETVAL) |
436
             IPCOP_MASK (GETPID) | IPCOP_MASK (GETNCNT) | IPCOP_MASK (GETZCNT) |
437
             IPCOP_MASK (GETALL) | IPCOP_MASK (SETALL) | IPCOP_MASK (IPC_RMID))) {
438
                err = sys_semctl (first, second, third, fourth);
439
        } else if (third & IPC_64) {
440
                struct semid64_ds s;
441
                struct semid64_ds32 *usp = (struct semid64_ds32 *)A(pad);
442
                mm_segment_t old_fs;
443
                int need_back_translation;
444
 
445
                if (third == (IPC_SET|IPC_64)) {
446
                        err = get_user (s.sem_perm.uid, &usp->sem_perm.uid);
447
                        err |= __get_user (s.sem_perm.gid, &usp->sem_perm.gid);
448
                        err |= __get_user (s.sem_perm.mode, &usp->sem_perm.mode);
449
                        if (err)
450
                                goto out;
451
                        fourth.__pad = &s;
452
                }
453
                need_back_translation =
454
                        (IPCOP_MASK (third) &
455
                         (IPCOP_MASK (SEM_STAT) | IPCOP_MASK (IPC_STAT))) != 0;
456
                if (need_back_translation)
457
                        fourth.__pad = &s;
458
                old_fs = get_fs ();
459
                set_fs (KERNEL_DS);
460
                err = sys_semctl (first, second, third, fourth);
461
                set_fs (old_fs);
462
                if (need_back_translation) {
463
                        int err2 = copy_to_user (&usp->sem_perm, &s.sem_perm, sizeof(struct ipc64_perm) + 2*sizeof(time_t));
464
                        err2 |= __put_user (s.sem_nsems, &usp->sem_nsems);
465
                        if (err2) err = -EFAULT;
466
                }
467
        } else {
468
                struct semid_ds s;
469
                struct semid_ds32 *usp = (struct semid_ds32 *)A(pad);
470
                mm_segment_t old_fs;
471
                int need_back_translation;
472
 
473
                if (third == IPC_SET) {
474
                        err = get_user (s.sem_perm.uid, &usp->sem_perm.uid);
475
                        err |= __get_user (s.sem_perm.gid, &usp->sem_perm.gid);
476
                        err |= __get_user (s.sem_perm.mode, &usp->sem_perm.mode);
477
                        if (err)
478
                                goto out;
479
                        fourth.__pad = &s;
480
                }
481
                need_back_translation =
482
                        (IPCOP_MASK (third) &
483
                         (IPCOP_MASK (SEM_STAT) | IPCOP_MASK (IPC_STAT))) != 0;
484
                if (need_back_translation)
485
                        fourth.__pad = &s;
486
                old_fs = get_fs ();
487
                set_fs (KERNEL_DS);
488
                err = sys_semctl (first, second, third, fourth);
489
                set_fs (old_fs);
490
                if (need_back_translation) {
491
                        int err2 = put_user (s.sem_perm.key, &usp->sem_perm.key);
492
                        err2 |= __put_user (high2lowuid(s.sem_perm.uid), &usp->sem_perm.uid);
493
                        err2 |= __put_user (high2lowgid(s.sem_perm.gid), &usp->sem_perm.gid);
494
                        err2 |= __put_user (high2lowuid(s.sem_perm.cuid), &usp->sem_perm.cuid);
495
                        err2 |= __put_user (high2lowgid(s.sem_perm.cgid), &usp->sem_perm.cgid);
496
                        err2 |= __put_user (s.sem_perm.mode, &usp->sem_perm.mode);
497
                        err2 |= __put_user (s.sem_perm.seq, &usp->sem_perm.seq);
498
                        err2 |= __put_user (s.sem_otime, &usp->sem_otime);
499
                        err2 |= __put_user (s.sem_ctime, &usp->sem_ctime);
500
                        err2 |= __put_user (s.sem_nsems, &usp->sem_nsems);
501
                        if (err2) err = -EFAULT;
502
                }
503
        }
504
out:
505
        return err;
506
}
507
 
508
static int do_sys32_msgsnd (int first, int second, int third, void *uptr)
509
{
510
        struct msgbuf *p = kmalloc (second + sizeof (struct msgbuf), GFP_USER);
511
        struct msgbuf32 *up = (struct msgbuf32 *)uptr;
512
        mm_segment_t old_fs;
513
        int err;
514
 
515
        if (!p)
516
                return -ENOMEM;
517
        err = -EFAULT;
518
        if (get_user (p->mtype, &up->mtype) ||
519
            __copy_from_user (p->mtext, &up->mtext, second))
520
                goto out;
521
        old_fs = get_fs ();
522
        set_fs (KERNEL_DS);
523
        err = sys_msgsnd (first, p, second, third);
524
        set_fs (old_fs);
525
out:
526
        kfree (p);
527
        return err;
528
}
529
 
530
static int do_sys32_msgrcv (int first, int second, int msgtyp, int third,
531
                            int version, void *uptr)
532
{
533
        struct msgbuf32 *up;
534
        struct msgbuf *p;
535
        mm_segment_t old_fs;
536
        int err;
537
 
538
        if (!version) {
539
                struct ipc_kludge *uipck = (struct ipc_kludge *)uptr;
540
                struct ipc_kludge ipck;
541
 
542
                err = -EINVAL;
543
                if (!uptr)
544
                        goto out;
545
                err = -EFAULT;
546
                if (copy_from_user (&ipck, uipck, sizeof (struct ipc_kludge)))
547
                        goto out;
548
                uptr = (void *)A(ipck.msgp);
549
                msgtyp = ipck.msgtyp;
550
        }
551
        err = -ENOMEM;
552
        p = kmalloc (second + sizeof (struct msgbuf), GFP_USER);
553
        if (!p)
554
                goto out;
555
        old_fs = get_fs ();
556
        set_fs (KERNEL_DS);
557
        err = sys_msgrcv (first, p, second, msgtyp, third);
558
        set_fs (old_fs);
559
        if (err < 0)
560
                goto free_then_out;
561
        up = (struct msgbuf32 *)uptr;
562
        if (put_user (p->mtype, &up->mtype) ||
563
            __copy_to_user (&up->mtext, p->mtext, err))
564
                err = -EFAULT;
565
free_then_out:
566
        kfree (p);
567
out:
568
        return err;
569
}
570
 
571
static int do_sys32_msgctl (int first, int second, void *uptr)
572
{
573
        int err;
574
 
575
        if (IPCOP_MASK (second) &
576
            (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (MSG_INFO) |
577
             IPCOP_MASK (IPC_RMID))) {
578
                err = sys_msgctl (first, second, (struct msqid_ds *)uptr);
579
        } else if (second & IPC_64) {
580
                struct msqid64_ds m;
581
                struct msqid64_ds32 *up = (struct msqid64_ds32 *)uptr;
582
                mm_segment_t old_fs;
583
 
584
                if (second == (IPC_SET|IPC_64)) {
585
                        err = get_user (m.msg_perm.uid, &up->msg_perm.uid);
586
                        err |= __get_user (m.msg_perm.gid, &up->msg_perm.gid);
587
                        err |= __get_user (m.msg_perm.mode, &up->msg_perm.mode);
588
                        err |= __get_user (m.msg_qbytes, &up->msg_qbytes);
589
                        if (err)
590
                                goto out;
591
                }
592
                old_fs = get_fs ();
593
                set_fs (KERNEL_DS);
594
                err = sys_msgctl (first, second, (struct msqid_ds *)&m);
595
                set_fs (old_fs);
596
                if (IPCOP_MASK (second) &
597
                    (IPCOP_MASK (MSG_STAT) | IPCOP_MASK (IPC_STAT))) {
598
                        int err2 = copy_to_user(&up->msg_perm, &m.msg_perm, sizeof(struct ipc64_perm) + 3*sizeof(time_t));
599
                        err2 |= __put_user (m.msg_cbytes, &up->msg_cbytes);
600
                        err2 |= __put_user (m.msg_qnum, &up->msg_qnum);
601
                        err2 |= __put_user (m.msg_qbytes, &up->msg_qbytes);
602
                        err2 |= __put_user (m.msg_lspid, &up->msg_lspid);
603
                        err2 |= __put_user (m.msg_lrpid, &up->msg_lrpid);
604
                        if (err2)
605
                                err = -EFAULT;
606
                }
607
        } else {
608
                struct msqid_ds m;
609
                struct msqid_ds32 *up = (struct msqid_ds32 *)uptr;
610
                mm_segment_t old_fs;
611
 
612
                if (second == IPC_SET) {
613
                        err = get_user (m.msg_perm.uid, &up->msg_perm.uid);
614
                        err |= __get_user (m.msg_perm.gid, &up->msg_perm.gid);
615
                        err |= __get_user (m.msg_perm.mode, &up->msg_perm.mode);
616
                        err |= __get_user (m.msg_qbytes, &up->msg_qbytes);
617
                        if (err)
618
                                goto out;
619
                }
620
                old_fs = get_fs ();
621
                set_fs (KERNEL_DS);
622
                err = sys_msgctl (first, second, &m);
623
                set_fs (old_fs);
624
                if (IPCOP_MASK (second) &
625
                    (IPCOP_MASK (MSG_STAT) | IPCOP_MASK (IPC_STAT))) {
626
                        int err2 = put_user (m.msg_perm.key, &up->msg_perm.key);
627
                        err2 |= __put_user (high2lowuid(m.msg_perm.uid), &up->msg_perm.uid);
628
                        err2 |= __put_user (high2lowgid(m.msg_perm.gid), &up->msg_perm.gid);
629
                        err2 |= __put_user (high2lowuid(m.msg_perm.cuid), &up->msg_perm.cuid);
630
                        err2 |= __put_user (high2lowgid(m.msg_perm.cgid), &up->msg_perm.cgid);
631
                        err2 |= __put_user (m.msg_perm.mode, &up->msg_perm.mode);
632
                        err2 |= __put_user (m.msg_perm.seq, &up->msg_perm.seq);
633
                        err2 |= __put_user (m.msg_stime, &up->msg_stime);
634
                        err2 |= __put_user (m.msg_rtime, &up->msg_rtime);
635
                        err2 |= __put_user (m.msg_ctime, &up->msg_ctime);
636
                        err2 |= __put_user (m.msg_cbytes, &up->msg_cbytes);
637
                        err2 |= __put_user (m.msg_qnum, &up->msg_qnum);
638
                        err2 |= __put_user (m.msg_qbytes, &up->msg_qbytes);
639
                        err2 |= __put_user (m.msg_lspid, &up->msg_lspid);
640
                        err2 |= __put_user (m.msg_lrpid, &up->msg_lrpid);
641
                        if (err2)
642
                                err = -EFAULT;
643
                }
644
        }
645
 
646
out:
647
        return err;
648
}
649
 
650
static int do_sys32_shmat (int first, int second, int third, int version, void *uptr)
651
{
652
        unsigned long raddr;
653
        u32 *uaddr = (u32 *)A((u32)third);
654
        int err = -EINVAL;
655
 
656
        if (version == 1)
657
                goto out;
658
        err = sys_shmat (first, uptr, second, &raddr);
659
        if (err)
660
                goto out;
661
        err = put_user (raddr, uaddr);
662
out:
663
        return err;
664
}
665
 
666
static int do_sys32_shmctl (int first, int second, void *uptr)
667
{
668
        int err;
669
 
670
        if (IPCOP_MASK (second) &
671
            (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (SHM_LOCK) | IPCOP_MASK (SHM_UNLOCK) |
672
             IPCOP_MASK (IPC_RMID))) {
673
                if (second == (IPC_INFO|IPC_64))
674
                        second = IPC_INFO; /* So that we don't have to translate it */
675
                err = sys_shmctl (first, second, (struct shmid_ds *)uptr);
676
        } else if ((second & IPC_64) && second != (SHM_INFO|IPC_64)) {
677
                struct shmid64_ds s;
678
                struct shmid64_ds32 *up = (struct shmid64_ds32 *)uptr;
679
                mm_segment_t old_fs;
680
 
681
                if (second == (IPC_SET|IPC_64)) {
682
                        err = get_user (s.shm_perm.uid, &up->shm_perm.uid);
683
                        err |= __get_user (s.shm_perm.gid, &up->shm_perm.gid);
684
                        err |= __get_user (s.shm_perm.mode, &up->shm_perm.mode);
685
                        if (err)
686
                                goto out;
687
                }
688
                old_fs = get_fs ();
689
                set_fs (KERNEL_DS);
690
                err = sys_shmctl (first, second, (struct shmid_ds *)&s);
691
                set_fs (old_fs);
692
                if (err < 0)
693
                        goto out;
694
 
695
                /* Mask it even in this case so it becomes a CSE. */
696
                if (IPCOP_MASK (second) &
697
                    (IPCOP_MASK (SHM_STAT) | IPCOP_MASK (IPC_STAT))) {
698
                        int err2 = copy_to_user (&up->shm_perm, &s.shm_perm, sizeof(struct ipc64_perm) + 3*sizeof(time_t));
699
                        err2 |= __put_user (s.shm_segsz, &up->shm_segsz);
700
                        err2 |= __put_user (s.shm_nattch, &up->shm_nattch);
701
                        err2 |= __put_user (s.shm_cpid, &up->shm_cpid);
702
                        err2 |= __put_user (s.shm_lpid, &up->shm_lpid);
703
                        if (err2)
704
                                err = -EFAULT;
705
                }
706
        } else {
707
                struct shmid_ds s;
708
                struct shmid_ds32 *up = (struct shmid_ds32 *)uptr;
709
                mm_segment_t old_fs;
710
 
711
                second &= ~IPC_64;
712
                if (second == IPC_SET) {
713
                        err = get_user (s.shm_perm.uid, &up->shm_perm.uid);
714
                        err |= __get_user (s.shm_perm.gid, &up->shm_perm.gid);
715
                        err |= __get_user (s.shm_perm.mode, &up->shm_perm.mode);
716
                        if (err)
717
                                goto out;
718
                }
719
                old_fs = get_fs ();
720
                set_fs (KERNEL_DS);
721
                err = sys_shmctl (first, second, &s);
722
                set_fs (old_fs);
723
                if (err < 0)
724
                        goto out;
725
 
726
                /* Mask it even in this case so it becomes a CSE. */
727
                if (second == SHM_INFO) {
728
                        struct shm_info32 {
729
                                int used_ids;
730
                                u32 shm_tot, shm_rss, shm_swp;
731
                                u32 swap_attempts, swap_successes;
732
                        } *uip = (struct shm_info32 *)uptr;
733
                        struct shm_info *kp = (struct shm_info *)&s;
734
                        int err2 = put_user (kp->used_ids, &uip->used_ids);
735
                        err2 |= __put_user (kp->shm_tot, &uip->shm_tot);
736
                        err2 |= __put_user (kp->shm_rss, &uip->shm_rss);
737
                        err2 |= __put_user (kp->shm_swp, &uip->shm_swp);
738
                        err2 |= __put_user (kp->swap_attempts, &uip->swap_attempts);
739
                        err2 |= __put_user (kp->swap_successes, &uip->swap_successes);
740
                        if (err2)
741
                                err = -EFAULT;
742
                } else if (IPCOP_MASK (second) &
743
                           (IPCOP_MASK (SHM_STAT) | IPCOP_MASK (IPC_STAT))) {
744
                        int err2 = put_user (s.shm_perm.key, &up->shm_perm.key);
745
                        err2 |= __put_user (high2lowuid(s.shm_perm.uid), &up->shm_perm.uid);
746
                        err2 |= __put_user (high2lowuid(s.shm_perm.gid), &up->shm_perm.gid);
747
                        err2 |= __put_user (high2lowuid(s.shm_perm.cuid), &up->shm_perm.cuid);
748
                        err2 |= __put_user (high2lowuid(s.shm_perm.cgid), &up->shm_perm.cgid);
749
                        err2 |= __put_user (s.shm_perm.mode, &up->shm_perm.mode);
750
                        err2 |= __put_user (s.shm_perm.seq, &up->shm_perm.seq);
751
                        err2 |= __put_user (s.shm_atime, &up->shm_atime);
752
                        err2 |= __put_user (s.shm_dtime, &up->shm_dtime);
753
                        err2 |= __put_user (s.shm_ctime, &up->shm_ctime);
754
                        err2 |= __put_user (s.shm_segsz, &up->shm_segsz);
755
                        err2 |= __put_user (s.shm_nattch, &up->shm_nattch);
756
                        err2 |= __put_user (s.shm_cpid, &up->shm_cpid);
757
                        err2 |= __put_user (s.shm_lpid, &up->shm_lpid);
758
                        if (err2)
759
                                err = -EFAULT;
760
                }
761
        }
762
out:
763
        return err;
764
}
765
 
766
static __inline__ void *alloc_user_space(long len)
767
{
768
        struct pt_regs *regs = current->thread.kregs;
769
        unsigned long usp = regs->u_regs[UREG_I6];
770
 
771
        if (!(current->thread.flags & SPARC_FLAG_32BIT))
772
                usp += STACK_BIAS;
773
 
774
        return (void *) (usp - len);
775
}
776
 
777
struct timespec32 {
778
        s32    tv_sec;
779
        s32    tv_nsec;
780
};
781
 
782
static int sys32_semtimedop(int semid, struct sembuf *tsems, int nsems,
783
                            const struct timespec32 *timeout32)
784
{
785
        struct timespec32 t32;
786
        struct timespec *t64 = alloc_user_space(sizeof(*t64));
787
 
788
        if (copy_from_user(&t32, timeout32, sizeof(t32)))
789
                return -EFAULT;
790
 
791
        if (put_user(t32.tv_sec, &t64->tv_sec) ||
792
            put_user(t32.tv_nsec, &t64->tv_nsec))
793
                return -EFAULT;
794
 
795
        return sys_semtimedop(semid, tsems, nsems, t64);
796
}
797
 
798
asmlinkage int sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
799
{
800
        int version, err;
801
 
802
        version = call >> 16; /* hack for backward compatibility */
803
        call &= 0xffff;
804
 
805
        if (call <= SEMCTL)
806
                switch (call) {
807
                case SEMOP:
808
                        /* struct sembuf is the same on 32 and 64bit :)) */
809
                        err = sys_semtimedop (first, (struct sembuf *)AA(ptr), second, NULL);
810
                        goto out;
811
                case SEMTIMEDOP:
812
                        err = sys32_semtimedop (first, (struct sembuf *)AA(ptr), second, (const struct timespec32 *) AA(fifth));
813
                case SEMGET:
814
                        err = sys_semget (first, second, third);
815
                        goto out;
816
                case SEMCTL:
817
                        err = do_sys32_semctl (first, second, third, (void *)AA(ptr));
818
                        goto out;
819
                default:
820
                        err = -ENOSYS;
821
                        goto out;
822
                };
823
        if (call <= MSGCTL)
824
                switch (call) {
825
                case MSGSND:
826
                        err = do_sys32_msgsnd (first, second, third, (void *)AA(ptr));
827
                        goto out;
828
                case MSGRCV:
829
                        err = do_sys32_msgrcv (first, second, fifth, third,
830
                                               version, (void *)AA(ptr));
831
                        goto out;
832
                case MSGGET:
833
                        err = sys_msgget ((key_t) first, second);
834
                        goto out;
835
                case MSGCTL:
836
                        err = do_sys32_msgctl (first, second, (void *)AA(ptr));
837
                        goto out;
838
                default:
839
                        err = -ENOSYS;
840
                        goto out;
841
                }
842
        if (call <= SHMCTL)
843
                switch (call) {
844
                case SHMAT:
845
                        err = do_sys32_shmat (first, second, third,
846
                                              version, (void *)AA(ptr));
847
                        goto out;
848
                case SHMDT:
849
                        err = sys_shmdt ((char *)AA(ptr));
850
                        goto out;
851
                case SHMGET:
852
                        err = sys_shmget (first, second, third);
853
                        goto out;
854
                case SHMCTL:
855
                        err = do_sys32_shmctl (first, second, (void *)AA(ptr));
856
                        goto out;
857
                default:
858
                        err = -ENOSYS;
859
                        goto out;
860
                }
861
 
862
        err = -ENOSYS;
863
 
864
out:
865
        return err;
866
}
867
 
868
static inline int get_flock(struct flock *kfl, struct flock32 *ufl)
869
{
870
        int err;
871
 
872
        err = get_user(kfl->l_type, &ufl->l_type);
873
        err |= __get_user(kfl->l_whence, &ufl->l_whence);
874
        err |= __get_user(kfl->l_start, &ufl->l_start);
875
        err |= __get_user(kfl->l_len, &ufl->l_len);
876
        err |= __get_user(kfl->l_pid, &ufl->l_pid);
877
        return err;
878
}
879
 
880
static inline int put_flock(struct flock *kfl, struct flock32 *ufl)
881
{
882
        int err;
883
 
884
        err = __put_user(kfl->l_type, &ufl->l_type);
885
        err |= __put_user(kfl->l_whence, &ufl->l_whence);
886
        err |= __put_user(kfl->l_start, &ufl->l_start);
887
        err |= __put_user(kfl->l_len, &ufl->l_len);
888
        err |= __put_user(kfl->l_pid, &ufl->l_pid);
889
        return err;
890
}
891
 
892
extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg);
893
 
894
asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
895
{
896
        switch (cmd) {
897
        case F_GETLK:
898
        case F_SETLK:
899
        case F_SETLKW:
900
                {
901
                        struct flock f;
902
                        mm_segment_t old_fs;
903
                        long ret;
904
 
905
                        if (get_flock(&f, (struct flock32 *)arg))
906
                                return -EFAULT;
907
                        old_fs = get_fs(); set_fs (KERNEL_DS);
908
                        ret = sys_fcntl(fd, cmd, (unsigned long)&f);
909
                        set_fs (old_fs);
910
                        if (ret) return ret;
911
                        if (put_flock(&f, (struct flock32 *)arg))
912
                                return -EFAULT;
913
                        return 0;
914
                }
915
        default:
916
                return sys_fcntl(fd, cmd, (unsigned long)arg);
917
        }
918
}
919
 
920
asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg)
921
{
922
        if (cmd >= F_GETLK64 && cmd <= F_SETLKW64)
923
                return sys_fcntl(fd, cmd + F_GETLK - F_GETLK64, arg);
924
        return sys32_fcntl(fd, cmd, arg);
925
}
926
 
927
struct user_dqblk32 {
928
    __u32 dqb_bhardlimit;
929
    __u32 dqb_bsoftlimit;
930
    __u32 dqb_curblocks;
931
    __u32 dqb_ihardlimit;
932
    __u32 dqb_isoftlimit;
933
    __u32 dqb_curinodes;
934
    __kernel_time_t32 dqb_btime;
935
    __kernel_time_t32 dqb_itime;
936
};
937
 
938
extern asmlinkage int sys_quotactl(int cmd, const char *special, int id, caddr_t addr);
939
 
940
asmlinkage int sys32_quotactl(int cmd, const char *special, int id, caddr_t addr)
941
{
942
        int cmds = cmd >> SUBCMDSHIFT;
943
        int err;
944
        struct v1c_mem_dqblk d;
945
        mm_segment_t old_fs;
946
        char *spec;
947
 
948
        switch (cmds) {
949
        case Q_V1_GETQUOTA:
950
                break;
951
        case Q_V1_SETQUOTA:
952
        case Q_V1_SETUSE:
953
        case Q_V1_SETQLIM:
954
                if (copy_from_user(&d, addr, sizeof(struct user_dqblk32)))
955
                        return -EFAULT;
956
                d.dqb_itime = ((struct user_dqblk32 *)&d)->dqb_itime;
957
                d.dqb_btime = ((struct user_dqblk32 *)&d)->dqb_btime;
958
                break;
959
        default:
960
                return sys_quotactl(cmd, special, id, addr);
961
        }
962
        spec = getname(special);
963
        err = PTR_ERR(spec);
964
        if (IS_ERR(spec))
965
                return err;
966
        old_fs = get_fs();
967
        set_fs (KERNEL_DS);
968
        err = sys_quotactl(cmd, (const char *)spec, id, (caddr_t)&d);
969
        set_fs (old_fs);
970
        putname (spec);
971
        if (cmds == Q_V1_GETQUOTA) {
972
                __kernel_time_t b = d.dqb_btime, i = d.dqb_itime;
973
                ((struct user_dqblk32 *)&d)->dqb_itime = i;
974
                ((struct user_dqblk32 *)&d)->dqb_btime = b;
975
                if (copy_to_user(addr, &d, sizeof(struct user_dqblk32)))
976
                        return -EFAULT;
977
        }
978
        return err;
979
}
980
 
981
static inline int put_statfs (struct statfs32 *ubuf, struct statfs *kbuf)
982
{
983
        int err;
984
 
985
        err = put_user (kbuf->f_type, &ubuf->f_type);
986
        err |= __put_user (kbuf->f_bsize, &ubuf->f_bsize);
987
        err |= __put_user (kbuf->f_blocks, &ubuf->f_blocks);
988
        err |= __put_user (kbuf->f_bfree, &ubuf->f_bfree);
989
        err |= __put_user (kbuf->f_bavail, &ubuf->f_bavail);
990
        err |= __put_user (kbuf->f_files, &ubuf->f_files);
991
        err |= __put_user (kbuf->f_ffree, &ubuf->f_ffree);
992
        err |= __put_user (kbuf->f_namelen, &ubuf->f_namelen);
993
        err |= __put_user (kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]);
994
        err |= __put_user (kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]);
995
        return err;
996
}
997
 
998
extern asmlinkage int sys_statfs(const char * path, struct statfs * buf);
999
 
1000
asmlinkage int sys32_statfs(const char * path, struct statfs32 *buf)
1001
{
1002
        int ret;
1003
        struct statfs s;
1004
        mm_segment_t old_fs = get_fs();
1005
        char *pth;
1006
 
1007
        pth = getname (path);
1008
        ret = PTR_ERR(pth);
1009
        if (!IS_ERR(pth)) {
1010
                set_fs (KERNEL_DS);
1011
                ret = sys_statfs((const char *)pth, &s);
1012
                set_fs (old_fs);
1013
                putname (pth);
1014
                if (put_statfs(buf, &s))
1015
                        return -EFAULT;
1016
        }
1017
        return ret;
1018
}
1019
 
1020
extern asmlinkage int sys_fstatfs(unsigned int fd, struct statfs * buf);
1021
 
1022
asmlinkage int sys32_fstatfs(unsigned int fd, struct statfs32 *buf)
1023
{
1024
        int ret;
1025
        struct statfs s;
1026
        mm_segment_t old_fs = get_fs();
1027
 
1028
        set_fs (KERNEL_DS);
1029
        ret = sys_fstatfs(fd, &s);
1030
        set_fs (old_fs);
1031
        if (put_statfs(buf, &s))
1032
                return -EFAULT;
1033
        return ret;
1034
}
1035
 
1036
extern asmlinkage long sys_truncate(const char * path, unsigned long length);
1037
extern asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length);
1038
 
1039
asmlinkage int sys32_truncate64(const char * path, unsigned long high, unsigned long low)
1040
{
1041
        if ((int)high < 0)
1042
                return -EINVAL;
1043
        else
1044
                return sys_truncate(path, (high << 32) | low);
1045
}
1046
 
1047
asmlinkage int sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned long low)
1048
{
1049
        if ((int)high < 0)
1050
                return -EINVAL;
1051
        else
1052
                return sys_ftruncate(fd, (high << 32) | low);
1053
}
1054
 
1055
extern asmlinkage int sys_utime(char * filename, struct utimbuf * times);
1056
 
1057
struct utimbuf32 {
1058
        __kernel_time_t32 actime, modtime;
1059
};
1060
 
1061
asmlinkage int sys32_utime(char * filename, struct utimbuf32 *times)
1062
{
1063
        struct utimbuf t;
1064
        mm_segment_t old_fs;
1065
        int ret;
1066
        char *filenam;
1067
 
1068
        if (!times)
1069
                return sys_utime(filename, NULL);
1070
        if (get_user (t.actime, &times->actime) ||
1071
            __get_user (t.modtime, &times->modtime))
1072
                return -EFAULT;
1073
        filenam = getname (filename);
1074
        ret = PTR_ERR(filenam);
1075
        if (!IS_ERR(filenam)) {
1076
                old_fs = get_fs();
1077
                set_fs (KERNEL_DS);
1078
                ret = sys_utime(filenam, &t);
1079
                set_fs (old_fs);
1080
                putname (filenam);
1081
        }
1082
        return ret;
1083
}
1084
 
1085
struct iovec32 { u32 iov_base; __kernel_size_t32 iov_len; };
1086
 
1087
typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *);
1088
typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *);
1089
 
1090
static long do_readv_writev32(int type, struct file *file,
1091
                              const struct iovec32 *vector, u32 count)
1092
{
1093
        __kernel_ssize_t32 tot_len;
1094
        struct iovec iovstack[UIO_FASTIOV];
1095
        struct iovec *iov=iovstack, *ivp;
1096
        struct inode *inode;
1097
        long retval, i;
1098
        io_fn_t fn;
1099
        iov_fn_t fnv;
1100
 
1101
        /* First get the "struct iovec" from user memory and
1102
         * verify all the pointers
1103
         */
1104
        retval = 0;
1105
        if (!count)
1106
                goto out_nofree;
1107
        retval = -EFAULT;
1108
        if (verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count))
1109
                goto out_nofree;
1110
        retval = -EINVAL;
1111
        if (count > UIO_MAXIOV)
1112
                goto out_nofree;
1113
        if (count > UIO_FASTIOV) {
1114
                retval = -ENOMEM;
1115
                iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL);
1116
                if (!iov)
1117
                        goto out_nofree;
1118
        }
1119
 
1120
        tot_len = 0;
1121
        i = count;
1122
        ivp = iov;
1123
        retval = -EINVAL;
1124
        while(i > 0) {
1125
                __kernel_ssize_t32 tmp = tot_len;
1126
                __kernel_ssize_t32 len;
1127
                u32 buf;
1128
 
1129
                __get_user(len, &vector->iov_len);
1130
                __get_user(buf, &vector->iov_base);
1131
                if (len < 0)     /* size_t not fittina an ssize_t32 .. */
1132
                        goto out;
1133
                tot_len += len;
1134
                if (tot_len < tmp) /* maths overflow on the ssize_t32 */
1135
                        goto out;
1136
                ivp->iov_base = (void *)A(buf);
1137
                ivp->iov_len = (__kernel_size_t) len;
1138
                vector++;
1139
                ivp++;
1140
                i--;
1141
        }
1142
 
1143
        inode = file->f_dentry->d_inode;
1144
        /* VERIFY_WRITE actually means a read, as we write to user space */
1145
        retval = locks_verify_area((type == VERIFY_WRITE
1146
                                    ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE),
1147
                                   inode, file, file->f_pos, tot_len);
1148
        if (retval)
1149
                goto out;
1150
 
1151
        /* VERIFY_WRITE actually means a read, as we write to user space */
1152
        fnv = (type == VERIFY_WRITE ? file->f_op->readv : file->f_op->writev);
1153
        if (fnv) {
1154
                retval = fnv(file, iov, count, &file->f_pos);
1155
                goto out;
1156
        }
1157
 
1158
        fn = (type == VERIFY_WRITE ? file->f_op->read :
1159
              (io_fn_t) file->f_op->write);
1160
 
1161
        ivp = iov;
1162
        while (count > 0) {
1163
                void * base;
1164
                int len, nr;
1165
 
1166
                base = ivp->iov_base;
1167
                len = ivp->iov_len;
1168
                ivp++;
1169
                count--;
1170
                nr = fn(file, base, len, &file->f_pos);
1171
                if (nr < 0) {
1172
                        if (!retval)
1173
                                retval = nr;
1174
                        break;
1175
                }
1176
                retval += nr;
1177
                if (nr != len)
1178
                        break;
1179
        }
1180
out:
1181
        if (iov != iovstack)
1182
                kfree(iov);
1183
out_nofree:
1184
        /* VERIFY_WRITE actually means a read, as we write to user space */
1185
        if ((retval + (type == VERIFY_WRITE)) > 0)
1186
                dnotify_parent(file->f_dentry,
1187
                        (type == VERIFY_WRITE) ? DN_ACCESS : DN_MODIFY);
1188
 
1189
        return retval;
1190
}
1191
 
1192
asmlinkage long sys32_readv(int fd, struct iovec32 *vector, u32 count)
1193
{
1194
        struct file *file;
1195
        long ret = -EBADF;
1196
 
1197
        file = fget(fd);
1198
        if(!file)
1199
                goto bad_file;
1200
 
1201
        if (file->f_op && (file->f_mode & FMODE_READ) &&
1202
            (file->f_op->readv || file->f_op->read))
1203
                ret = do_readv_writev32(VERIFY_WRITE, file, vector, count);
1204
        fput(file);
1205
 
1206
bad_file:
1207
        return ret;
1208
}
1209
 
1210
asmlinkage long sys32_writev(int fd, struct iovec32 *vector, u32 count)
1211
{
1212
        struct file *file;
1213
        int ret = -EBADF;
1214
 
1215
        file = fget(fd);
1216
        if(!file)
1217
                goto bad_file;
1218
        if (file->f_op && (file->f_mode & FMODE_WRITE) &&
1219
            (file->f_op->writev || file->f_op->write))
1220
                ret = do_readv_writev32(VERIFY_READ, file, vector, count);
1221
        fput(file);
1222
 
1223
bad_file:
1224
        return ret;
1225
}
1226
 
1227
/* readdir & getdents */
1228
 
1229
#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
1230
#define ROUND_UP(x) (((x)+sizeof(u32)-1) & ~(sizeof(u32)-1))
1231
 
1232
struct old_linux_dirent32 {
1233
        u32             d_ino;
1234
        u32             d_offset;
1235
        unsigned short  d_namlen;
1236
        char            d_name[1];
1237
};
1238
 
1239
struct readdir_callback32 {
1240
        struct old_linux_dirent32 * dirent;
1241
        int count;
1242
};
1243
 
1244
static int fillonedir(void * __buf, const char * name, int namlen,
1245
                      loff_t offset, ino_t ino, unsigned int d_type)
1246
{
1247
        struct readdir_callback32 * buf = (struct readdir_callback32 *) __buf;
1248
        struct old_linux_dirent32 * dirent;
1249
 
1250
        if (buf->count)
1251
                return -EINVAL;
1252
        buf->count++;
1253
        dirent = buf->dirent;
1254
        put_user(ino, &dirent->d_ino);
1255
        put_user(offset, &dirent->d_offset);
1256
        put_user(namlen, &dirent->d_namlen);
1257
        copy_to_user(dirent->d_name, name, namlen);
1258
        put_user(0, dirent->d_name + namlen);
1259
        return 0;
1260
}
1261
 
1262
asmlinkage int old32_readdir(unsigned int fd, struct old_linux_dirent32 *dirent, unsigned int count)
1263
{
1264
        int error = -EBADF;
1265
        struct file * file;
1266
        struct readdir_callback32 buf;
1267
 
1268
        file = fget(fd);
1269
        if (!file)
1270
                goto out;
1271
 
1272
        buf.count = 0;
1273
        buf.dirent = dirent;
1274
 
1275
        error = vfs_readdir(file, fillonedir, &buf);
1276
        if (error < 0)
1277
                goto out_putf;
1278
        error = buf.count;
1279
 
1280
out_putf:
1281
        fput(file);
1282
out:
1283
        return error;
1284
}
1285
 
1286
struct linux_dirent32 {
1287
        u32             d_ino;
1288
        u32             d_off;
1289
        unsigned short  d_reclen;
1290
        char            d_name[1];
1291
};
1292
 
1293
struct getdents_callback32 {
1294
        struct linux_dirent32 * current_dir;
1295
        struct linux_dirent32 * previous;
1296
        int count;
1297
        int error;
1298
};
1299
 
1300
static int filldir(void * __buf, const char * name, int namlen, loff_t offset, ino_t ino,
1301
                   unsigned int d_type)
1302
{
1303
        struct linux_dirent32 * dirent;
1304
        struct getdents_callback32 * buf = (struct getdents_callback32 *) __buf;
1305
        int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
1306
 
1307
        buf->error = -EINVAL;   /* only used if we fail.. */
1308
        if (reclen > buf->count)
1309
                return -EINVAL;
1310
        dirent = buf->previous;
1311
        if (dirent)
1312
                put_user(offset, &dirent->d_off);
1313
        dirent = buf->current_dir;
1314
        buf->previous = dirent;
1315
        put_user(ino, &dirent->d_ino);
1316
        put_user(reclen, &dirent->d_reclen);
1317
        copy_to_user(dirent->d_name, name, namlen);
1318
        put_user(0, dirent->d_name + namlen);
1319
        ((char *) dirent) += reclen;
1320
        buf->current_dir = dirent;
1321
        buf->count -= reclen;
1322
        return 0;
1323
}
1324
 
1325
asmlinkage int sys32_getdents(unsigned int fd, struct linux_dirent32 *dirent, unsigned int count)
1326
{
1327
        struct file * file;
1328
        struct linux_dirent32 * lastdirent;
1329
        struct getdents_callback32 buf;
1330
        int error = -EBADF;
1331
 
1332
        file = fget(fd);
1333
        if (!file)
1334
                goto out;
1335
 
1336
        buf.current_dir = dirent;
1337
        buf.previous = NULL;
1338
        buf.count = count;
1339
        buf.error = 0;
1340
 
1341
        error = vfs_readdir(file, filldir, &buf);
1342
        if (error < 0)
1343
                goto out_putf;
1344
        lastdirent = buf.previous;
1345
        error = buf.error;
1346
        if(lastdirent) {
1347
                put_user(file->f_pos, &lastdirent->d_off);
1348
                error = count - buf.count;
1349
        }
1350
out_putf:
1351
        fput(file);
1352
out:
1353
        return error;
1354
}
1355
 
1356
/* end of readdir & getdents */
1357
 
1358
/*
1359
 * Ooo, nasty.  We need here to frob 32-bit unsigned longs to
1360
 * 64-bit unsigned longs.
1361
 */
1362
 
1363
static inline int
1364
get_fd_set32(unsigned long n, unsigned long *fdset, u32 *ufdset)
1365
{
1366
        if (ufdset) {
1367
                unsigned long odd;
1368
 
1369
                if (verify_area(VERIFY_WRITE, ufdset, n*sizeof(u32)))
1370
                        return -EFAULT;
1371
 
1372
                odd = n & 1UL;
1373
                n &= ~1UL;
1374
                while (n) {
1375
                        unsigned long h, l;
1376
                        __get_user(l, ufdset);
1377
                        __get_user(h, ufdset+1);
1378
                        ufdset += 2;
1379
                        *fdset++ = h << 32 | l;
1380
                        n -= 2;
1381
                }
1382
                if (odd)
1383
                        __get_user(*fdset, ufdset);
1384
        } else {
1385
                /* Tricky, must clear full unsigned long in the
1386
                 * kernel fdset at the end, this makes sure that
1387
                 * actually happens.
1388
                 */
1389
                memset(fdset, 0, ((n + 1) & ~1)*sizeof(u32));
1390
        }
1391
        return 0;
1392
}
1393
 
1394
static inline void
1395
set_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset)
1396
{
1397
        unsigned long odd;
1398
 
1399
        if (!ufdset)
1400
                return;
1401
 
1402
        odd = n & 1UL;
1403
        n &= ~1UL;
1404
        while (n) {
1405
                unsigned long h, l;
1406
                l = *fdset++;
1407
                h = l >> 32;
1408
                __put_user(l, ufdset);
1409
                __put_user(h, ufdset+1);
1410
                ufdset += 2;
1411
                n -= 2;
1412
        }
1413
        if (odd)
1414
                __put_user(*fdset, ufdset);
1415
}
1416
 
1417
#define MAX_SELECT_SECONDS \
1418
        ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
1419
 
1420
asmlinkage int sys32_select(int n, u32 *inp, u32 *outp, u32 *exp, u32 tvp_x)
1421
{
1422
        fd_set_bits fds;
1423
        struct timeval32 *tvp = (struct timeval32 *)AA(tvp_x);
1424
        char *bits;
1425
        unsigned long nn;
1426
        long timeout;
1427
        int ret, size;
1428
 
1429
        timeout = MAX_SCHEDULE_TIMEOUT;
1430
        if (tvp) {
1431
                time_t sec, usec;
1432
 
1433
                if ((ret = verify_area(VERIFY_READ, tvp, sizeof(*tvp)))
1434
                    || (ret = __get_user(sec, &tvp->tv_sec))
1435
                    || (ret = __get_user(usec, &tvp->tv_usec)))
1436
                        goto out_nofds;
1437
 
1438
                ret = -EINVAL;
1439
                if(sec < 0 || usec < 0)
1440
                        goto out_nofds;
1441
 
1442
                if ((unsigned long) sec < MAX_SELECT_SECONDS) {
1443
                        timeout = (usec + 1000000/HZ - 1) / (1000000/HZ);
1444
                        timeout += sec * (unsigned long) HZ;
1445
                }
1446
        }
1447
 
1448
        ret = -EINVAL;
1449
        if (n < 0)
1450
                goto out_nofds;
1451
        if (n > current->files->max_fdset)
1452
                n = current->files->max_fdset;
1453
 
1454
        /*
1455
         * We need 6 bitmaps (in/out/ex for both incoming and outgoing),
1456
         * since we used fdset we need to allocate memory in units of
1457
         * long-words.
1458
         */
1459
        ret = -ENOMEM;
1460
        size = FDS_BYTES(n);
1461
        bits = kmalloc(6 * size, GFP_KERNEL);
1462
        if (!bits)
1463
                goto out_nofds;
1464
        fds.in      = (unsigned long *)  bits;
1465
        fds.out     = (unsigned long *) (bits +   size);
1466
        fds.ex      = (unsigned long *) (bits + 2*size);
1467
        fds.res_in  = (unsigned long *) (bits + 3*size);
1468
        fds.res_out = (unsigned long *) (bits + 4*size);
1469
        fds.res_ex  = (unsigned long *) (bits + 5*size);
1470
 
1471
        nn = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32));
1472
        if ((ret = get_fd_set32(nn, fds.in, inp)) ||
1473
            (ret = get_fd_set32(nn, fds.out, outp)) ||
1474
            (ret = get_fd_set32(nn, fds.ex, exp)))
1475
                goto out;
1476
        zero_fd_set(n, fds.res_in);
1477
        zero_fd_set(n, fds.res_out);
1478
        zero_fd_set(n, fds.res_ex);
1479
 
1480
        ret = do_select(n, &fds, &timeout);
1481
 
1482
        if (tvp && !(current->personality & STICKY_TIMEOUTS)) {
1483
                time_t sec = 0, usec = 0;
1484
                if (timeout) {
1485
                        sec = timeout / HZ;
1486
                        usec = timeout % HZ;
1487
                        usec *= (1000000/HZ);
1488
                }
1489
                put_user(sec, &tvp->tv_sec);
1490
                put_user(usec, &tvp->tv_usec);
1491
        }
1492
 
1493
        if (ret < 0)
1494
                goto out;
1495
        if (!ret) {
1496
                ret = -ERESTARTNOHAND;
1497
                if (signal_pending(current))
1498
                        goto out;
1499
                ret = 0;
1500
        }
1501
 
1502
        set_fd_set32(nn, inp, fds.res_in);
1503
        set_fd_set32(nn, outp, fds.res_out);
1504
        set_fd_set32(nn, exp, fds.res_ex);
1505
 
1506
out:
1507
        kfree(bits);
1508
out_nofds:
1509
        return ret;
1510
}
1511
 
1512
static int cp_new_stat32(struct inode *inode, struct stat32 *statbuf)
1513
{
1514
        unsigned long ino, blksize, blocks;
1515
        kdev_t dev, rdev;
1516
        umode_t mode;
1517
        nlink_t nlink;
1518
        uid_t uid;
1519
        gid_t gid;
1520
        off_t size;
1521
        time_t atime, mtime, ctime;
1522
        int err;
1523
 
1524
        /* Stream the loads of inode data into the load buffer,
1525
         * then we push it all into the store buffer below.  This
1526
         * should give optimal cache performance.
1527
         */
1528
        ino = inode->i_ino;
1529
        dev = inode->i_dev;
1530
        mode = inode->i_mode;
1531
        nlink = inode->i_nlink;
1532
        uid = inode->i_uid;
1533
        gid = inode->i_gid;
1534
        rdev = inode->i_rdev;
1535
        size = inode->i_size;
1536
        atime = inode->i_atime;
1537
        mtime = inode->i_mtime;
1538
        ctime = inode->i_ctime;
1539
        blksize = inode->i_blksize;
1540
        blocks = inode->i_blocks;
1541
 
1542
        err  = put_user(kdev_t_to_nr(dev), &statbuf->st_dev);
1543
        err |= put_user(ino, &statbuf->st_ino);
1544
        err |= put_user(mode, &statbuf->st_mode);
1545
        err |= put_user(nlink, &statbuf->st_nlink);
1546
        err |= put_user(high2lowuid(uid), &statbuf->st_uid);
1547
        err |= put_user(high2lowgid(gid), &statbuf->st_gid);
1548
        err |= put_user(kdev_t_to_nr(rdev), &statbuf->st_rdev);
1549
        err |= put_user(size, &statbuf->st_size);
1550
        err |= put_user(atime, &statbuf->st_atime);
1551
        err |= put_user(0, &statbuf->__unused1);
1552
        err |= put_user(mtime, &statbuf->st_mtime);
1553
        err |= put_user(0, &statbuf->__unused2);
1554
        err |= put_user(ctime, &statbuf->st_ctime);
1555
        err |= put_user(0, &statbuf->__unused3);
1556
        if (blksize) {
1557
                err |= put_user(blksize, &statbuf->st_blksize);
1558
                err |= put_user(blocks, &statbuf->st_blocks);
1559
        } else {
1560
                unsigned int tmp_blocks;
1561
 
1562
#define D_B   7
1563
#define I_B   (BLOCK_SIZE / sizeof(unsigned short))
1564
                tmp_blocks = (size + BLOCK_SIZE - 1) / BLOCK_SIZE;
1565
                if (tmp_blocks > D_B) {
1566
                        unsigned int indirect;
1567
 
1568
                        indirect = (tmp_blocks - D_B + I_B - 1) / I_B;
1569
                        tmp_blocks += indirect;
1570
                        if (indirect > 1) {
1571
                                indirect = (indirect - 1 + I_B - 1) / I_B;
1572
                                tmp_blocks += indirect;
1573
                                if (indirect > 1)
1574
                                        tmp_blocks++;
1575
                        }
1576
                }
1577
                err |= put_user(BLOCK_SIZE, &statbuf->st_blksize);
1578
                err |= put_user((BLOCK_SIZE / 512) * tmp_blocks, &statbuf->st_blocks);
1579
#undef D_B
1580
#undef I_B
1581
        }
1582
        err |= put_user(0, &statbuf->__unused4[0]);
1583
        err |= put_user(0, &statbuf->__unused4[1]);
1584
 
1585
        return err;
1586
}
1587
 
1588
/* Perhaps this belongs in fs.h or similar. -DaveM */
1589
static __inline__ int
1590
do_revalidate(struct dentry *dentry)
1591
{
1592
        struct inode * inode = dentry->d_inode;
1593
        if (inode->i_op && inode->i_op->revalidate)
1594
                return inode->i_op->revalidate(dentry);
1595
        return 0;
1596
}
1597
 
1598
asmlinkage int sys32_newstat(char * filename, struct stat32 *statbuf)
1599
{
1600
        struct nameidata nd;
1601
        int error;
1602
 
1603
        error = user_path_walk(filename, &nd);
1604
        if (!error) {
1605
                error = do_revalidate(nd.dentry);
1606
                if (!error)
1607
                        error = cp_new_stat32(nd.dentry->d_inode, statbuf);
1608
                path_release(&nd);
1609
        }
1610
        return error;
1611
}
1612
 
1613
asmlinkage int sys32_newlstat(char * filename, struct stat32 *statbuf)
1614
{
1615
        struct nameidata nd;
1616
        int error;
1617
 
1618
        error = user_path_walk_link(filename, &nd);
1619
        if (!error) {
1620
                error = do_revalidate(nd.dentry);
1621
                if (!error)
1622
                        error = cp_new_stat32(nd.dentry->d_inode, statbuf);
1623
 
1624
                path_release(&nd);
1625
        }
1626
        return error;
1627
}
1628
 
1629
asmlinkage int sys32_newfstat(unsigned int fd, struct stat32 *statbuf)
1630
{
1631
        struct file *f;
1632
        int err = -EBADF;
1633
 
1634
        f = fget(fd);
1635
        if (f) {
1636
                struct dentry * dentry = f->f_dentry;
1637
 
1638
                err = do_revalidate(dentry);
1639
                if (!err)
1640
                        err = cp_new_stat32(dentry->d_inode, statbuf);
1641
                fput(f);
1642
        }
1643
        return err;
1644
}
1645
 
1646
extern asmlinkage int sys_sysfs(int option, unsigned long arg1, unsigned long arg2);
1647
 
1648
asmlinkage int sys32_sysfs(int option, u32 arg1, u32 arg2)
1649
{
1650
        return sys_sysfs(option, arg1, arg2);
1651
}
1652
 
1653
struct ncp_mount_data32_v3 {
1654
        int version;
1655
        unsigned int ncp_fd;
1656
        __kernel_uid_t32 mounted_uid;
1657
        __kernel_pid_t32 wdog_pid;
1658
        unsigned char mounted_vol[NCP_VOLNAME_LEN + 1];
1659
        unsigned int time_out;
1660
        unsigned int retry_count;
1661
        unsigned int flags;
1662
        __kernel_uid_t32 uid;
1663
        __kernel_gid_t32 gid;
1664
        __kernel_mode_t32 file_mode;
1665
        __kernel_mode_t32 dir_mode;
1666
};
1667
 
1668
struct ncp_mount_data32_v4 {
1669
        int version;
1670
        /* all members below are "long" in ABI ... i.e. 32bit on sparc32, while 64bits on sparc64 */
1671
        unsigned int flags;
1672
        unsigned int mounted_uid;
1673
        int wdog_pid;
1674
 
1675
        unsigned int ncp_fd;
1676
        unsigned int time_out;
1677
        unsigned int retry_count;
1678
 
1679
        unsigned int uid;
1680
        unsigned int gid;
1681
        unsigned int file_mode;
1682
        unsigned int dir_mode;
1683
};
1684
 
1685
static void *do_ncp_super_data_conv(void *raw_data)
1686
{
1687
        switch (*(int*)raw_data) {
1688
                case NCP_MOUNT_VERSION:
1689
                        {
1690
                                struct ncp_mount_data news, *n = &news;
1691
                                struct ncp_mount_data32_v3 *n32 = (struct ncp_mount_data32_v3 *)raw_data;
1692
 
1693
                                n->version = n32->version;
1694
                                n->ncp_fd = n32->ncp_fd;
1695
                                n->mounted_uid = low2highuid(n32->mounted_uid);
1696
                                n->wdog_pid = n32->wdog_pid;
1697
                                memmove (n->mounted_vol, n32->mounted_vol, sizeof (n32->mounted_vol));
1698
                                n->time_out = n32->time_out;
1699
                                n->retry_count = n32->retry_count;
1700
                                n->flags = n32->flags;
1701
                                n->uid = low2highuid(n32->uid);
1702
                                n->gid = low2highgid(n32->gid);
1703
                                n->file_mode = n32->file_mode;
1704
                                n->dir_mode = n32->dir_mode;
1705
                                memcpy(raw_data, n, sizeof(*n));
1706
                        }
1707
                        break;
1708
                case NCP_MOUNT_VERSION_V4:
1709
                        {
1710
                                struct ncp_mount_data_v4 news, *n = &news;
1711
                                struct ncp_mount_data32_v4 *n32 = (struct ncp_mount_data32_v4 *)raw_data;
1712
 
1713
                                n->version = n32->version;
1714
                                n->flags = n32->flags;
1715
                                n->mounted_uid = n32->mounted_uid;
1716
                                n->wdog_pid = n32->wdog_pid;
1717
                                n->ncp_fd = n32->ncp_fd;
1718
                                n->time_out = n32->time_out;
1719
                                n->retry_count = n32->retry_count;
1720
                                n->uid = n32->uid;
1721
                                n->gid = n32->gid;
1722
                                n->file_mode = n32->file_mode;
1723
                                n->dir_mode = n32->dir_mode;
1724
                                memcpy(raw_data, n, sizeof(*n));
1725
                        }
1726
                        break;
1727
                default:
1728
                        /* do not touch unknown structures */
1729
                        break;
1730
        }
1731
        return raw_data;
1732
}
1733
 
1734
struct smb_mount_data32 {
1735
        int version;
1736
        __kernel_uid_t32 mounted_uid;
1737
        __kernel_uid_t32 uid;
1738
        __kernel_gid_t32 gid;
1739
        __kernel_mode_t32 file_mode;
1740
        __kernel_mode_t32 dir_mode;
1741
};
1742
 
1743
static void *do_smb_super_data_conv(void *raw_data)
1744
{
1745
        struct smb_mount_data news, *s = &news;
1746
        struct smb_mount_data32 *s32 = (struct smb_mount_data32 *)raw_data;
1747
 
1748
        s->version = s32->version;
1749
        s->mounted_uid = low2highuid(s32->mounted_uid);
1750
        s->uid = low2highuid(s32->uid);
1751
        s->gid = low2highgid(s32->gid);
1752
        s->file_mode = s32->file_mode;
1753
        s->dir_mode = s32->dir_mode;
1754
        memcpy(raw_data, s, sizeof(struct smb_mount_data));
1755
        return raw_data;
1756
}
1757
 
1758
static int copy_mount_stuff_to_kernel(const void *user, unsigned long *kernel)
1759
{
1760
        int i;
1761
        unsigned long page;
1762
        struct vm_area_struct *vma;
1763
 
1764
        *kernel = 0;
1765
        if(!user)
1766
                return 0;
1767
        vma = find_vma(current->mm, (unsigned long)user);
1768
        if(!vma || (unsigned long)user < vma->vm_start)
1769
                return -EFAULT;
1770
        if(!(vma->vm_flags & VM_READ))
1771
                return -EFAULT;
1772
        i = vma->vm_end - (unsigned long) user;
1773
        if(PAGE_SIZE <= (unsigned long) i)
1774
                i = PAGE_SIZE - 1;
1775
        if(!(page = __get_free_page(GFP_KERNEL)))
1776
                return -ENOMEM;
1777
        if(copy_from_user((void *) page, user, i)) {
1778
                free_page(page);
1779
                return -EFAULT;
1780
        }
1781
        *kernel = page;
1782
        return 0;
1783
}
1784
 
1785
#define SMBFS_NAME      "smbfs"
1786
#define NCPFS_NAME      "ncpfs"
1787
 
1788
asmlinkage int sys32_mount(char *dev_name, char *dir_name, char *type, unsigned long new_flags, u32 data)
1789
{
1790
        unsigned long type_page = 0;
1791
        unsigned long data_page = 0;
1792
        unsigned long dev_page = 0;
1793
        unsigned long dir_page = 0;
1794
        int err, is_smb, is_ncp;
1795
 
1796
        is_smb = is_ncp = 0;
1797
 
1798
        err = copy_mount_stuff_to_kernel((const void *)type, &type_page);
1799
        if (err)
1800
                goto out;
1801
 
1802
        if (type_page) {
1803
                is_smb = !strcmp((char *)type_page, SMBFS_NAME);
1804
                is_ncp = !strcmp((char *)type_page, NCPFS_NAME);
1805
        } else {
1806
                is_smb = is_ncp = 0;
1807
        }
1808
 
1809
        err = copy_mount_stuff_to_kernel((const void *)AA(data), &data_page);
1810
        if (err)
1811
                goto type_out;
1812
 
1813
        err = copy_mount_stuff_to_kernel(dev_name, &dev_page);
1814
        if (err)
1815
                goto data_out;
1816
 
1817
        err = copy_mount_stuff_to_kernel(dir_name, &dir_page);
1818
        if (err)
1819
                goto dev_out;
1820
 
1821
        if (!is_smb && !is_ncp) {
1822
                lock_kernel();
1823
                err = do_mount((char*)dev_page, (char*)dir_page,
1824
                                (char*)type_page, new_flags, (char*)data_page);
1825
                unlock_kernel();
1826
        } else {
1827
                if (is_ncp)
1828
                        do_ncp_super_data_conv((void *)data_page);
1829
                else
1830
                        do_smb_super_data_conv((void *)data_page);
1831
 
1832
                lock_kernel();
1833
                err = do_mount((char*)dev_page, (char*)dir_page,
1834
                                (char*)type_page, new_flags, (char*)data_page);
1835
                unlock_kernel();
1836
        }
1837
        free_page(dir_page);
1838
 
1839
dev_out:
1840
        free_page(dev_page);
1841
 
1842
data_out:
1843
        free_page(data_page);
1844
 
1845
type_out:
1846
        free_page(type_page);
1847
 
1848
out:
1849
        return err;
1850
}
1851
 
1852
struct rusage32 {
1853
        struct timeval32 ru_utime;
1854
        struct timeval32 ru_stime;
1855
        s32    ru_maxrss;
1856
        s32    ru_ixrss;
1857
        s32    ru_idrss;
1858
        s32    ru_isrss;
1859
        s32    ru_minflt;
1860
        s32    ru_majflt;
1861
        s32    ru_nswap;
1862
        s32    ru_inblock;
1863
        s32    ru_oublock;
1864
        s32    ru_msgsnd;
1865
        s32    ru_msgrcv;
1866
        s32    ru_nsignals;
1867
        s32    ru_nvcsw;
1868
        s32    ru_nivcsw;
1869
};
1870
 
1871
static int put_rusage (struct rusage32 *ru, struct rusage *r)
1872
{
1873
        int err;
1874
 
1875
        err = put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec);
1876
        err |= __put_user (r->ru_utime.tv_usec, &ru->ru_utime.tv_usec);
1877
        err |= __put_user (r->ru_stime.tv_sec, &ru->ru_stime.tv_sec);
1878
        err |= __put_user (r->ru_stime.tv_usec, &ru->ru_stime.tv_usec);
1879
        err |= __put_user (r->ru_maxrss, &ru->ru_maxrss);
1880
        err |= __put_user (r->ru_ixrss, &ru->ru_ixrss);
1881
        err |= __put_user (r->ru_idrss, &ru->ru_idrss);
1882
        err |= __put_user (r->ru_isrss, &ru->ru_isrss);
1883
        err |= __put_user (r->ru_minflt, &ru->ru_minflt);
1884
        err |= __put_user (r->ru_majflt, &ru->ru_majflt);
1885
        err |= __put_user (r->ru_nswap, &ru->ru_nswap);
1886
        err |= __put_user (r->ru_inblock, &ru->ru_inblock);
1887
        err |= __put_user (r->ru_oublock, &ru->ru_oublock);
1888
        err |= __put_user (r->ru_msgsnd, &ru->ru_msgsnd);
1889
        err |= __put_user (r->ru_msgrcv, &ru->ru_msgrcv);
1890
        err |= __put_user (r->ru_nsignals, &ru->ru_nsignals);
1891
        err |= __put_user (r->ru_nvcsw, &ru->ru_nvcsw);
1892
        err |= __put_user (r->ru_nivcsw, &ru->ru_nivcsw);
1893
        return err;
1894
}
1895
 
1896
asmlinkage int sys32_wait4(__kernel_pid_t32 pid, unsigned int *stat_addr, int options, struct rusage32 *ru)
1897
{
1898
        if (!ru)
1899
                return sys_wait4(pid, stat_addr, options, NULL);
1900
        else {
1901
                struct rusage r;
1902
                int ret;
1903
                unsigned int status;
1904
                mm_segment_t old_fs = get_fs();
1905
 
1906
                set_fs (KERNEL_DS);
1907
                ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r);
1908
                set_fs (old_fs);
1909
                if (put_rusage (ru, &r)) return -EFAULT;
1910
                if (stat_addr && put_user (status, stat_addr))
1911
                        return -EFAULT;
1912
                return ret;
1913
        }
1914
}
1915
 
1916
struct sysinfo32 {
1917
        s32 uptime;
1918
        u32 loads[3];
1919
        u32 totalram;
1920
        u32 freeram;
1921
        u32 sharedram;
1922
        u32 bufferram;
1923
        u32 totalswap;
1924
        u32 freeswap;
1925
        unsigned short procs;
1926
        unsigned short pad;
1927
        u32 totalhigh;
1928
        u32 freehigh;
1929
        u32 mem_unit;
1930
        char _f[20-2*sizeof(int)-sizeof(int)];
1931
};
1932
 
1933
extern asmlinkage int sys_sysinfo(struct sysinfo *info);
1934
 
1935
asmlinkage int sys32_sysinfo(struct sysinfo32 *info)
1936
{
1937
        struct sysinfo s;
1938
        int ret, err;
1939
        int bitcount = 0;
1940
        mm_segment_t old_fs = get_fs ();
1941
 
1942
        set_fs(KERNEL_DS);
1943
        ret = sys_sysinfo(&s);
1944
        set_fs(old_fs);
1945
        /* Check to see if any memory value is too large for 32-bit and
1946
         * scale down if needed.
1947
         */
1948
        if ((s.totalram >> 32) || (s.totalswap >> 32)) {
1949
                while (s.mem_unit < PAGE_SIZE) {
1950
                        s.mem_unit <<= 1;
1951
                        bitcount++;
1952
                }
1953
                s.totalram >>= bitcount;
1954
                s.freeram >>= bitcount;
1955
                s.sharedram >>= bitcount;
1956
                s.bufferram >>= bitcount;
1957
                s.totalswap >>= bitcount;
1958
                s.freeswap >>= bitcount;
1959
                s.totalhigh >>= bitcount;
1960
                s.freehigh >>= bitcount;
1961
        }
1962
 
1963
        err = put_user (s.uptime, &info->uptime);
1964
        err |= __put_user (s.loads[0], &info->loads[0]);
1965
        err |= __put_user (s.loads[1], &info->loads[1]);
1966
        err |= __put_user (s.loads[2], &info->loads[2]);
1967
        err |= __put_user (s.totalram, &info->totalram);
1968
        err |= __put_user (s.freeram, &info->freeram);
1969
        err |= __put_user (s.sharedram, &info->sharedram);
1970
        err |= __put_user (s.bufferram, &info->bufferram);
1971
        err |= __put_user (s.totalswap, &info->totalswap);
1972
        err |= __put_user (s.freeswap, &info->freeswap);
1973
        err |= __put_user (s.procs, &info->procs);
1974
        err |= __put_user (s.totalhigh, &info->totalhigh);
1975
        err |= __put_user (s.freehigh, &info->freehigh);
1976
        err |= __put_user (s.mem_unit, &info->mem_unit);
1977
        if (err)
1978
                return -EFAULT;
1979
        return ret;
1980
}
1981
 
1982
extern asmlinkage int sys_sched_rr_get_interval(pid_t pid, struct timespec *interval);
1983
 
1984
asmlinkage int sys32_sched_rr_get_interval(__kernel_pid_t32 pid, struct timespec32 *interval)
1985
{
1986
        struct timespec t;
1987
        int ret;
1988
        mm_segment_t old_fs = get_fs ();
1989
 
1990
        set_fs (KERNEL_DS);
1991
        ret = sys_sched_rr_get_interval(pid, &t);
1992
        set_fs (old_fs);
1993
        if (put_user (t.tv_sec, &interval->tv_sec) ||
1994
            __put_user (t.tv_nsec, &interval->tv_nsec))
1995
                return -EFAULT;
1996
        return ret;
1997
}
1998
 
1999
extern asmlinkage int sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp);
2000
 
2001
asmlinkage int sys32_nanosleep(struct timespec32 *rqtp, struct timespec32 *rmtp)
2002
{
2003
        struct timespec t;
2004
        int ret;
2005
        mm_segment_t old_fs = get_fs ();
2006
 
2007
        if (get_user (t.tv_sec, &rqtp->tv_sec) ||
2008
            __get_user (t.tv_nsec, &rqtp->tv_nsec))
2009
                return -EFAULT;
2010
        set_fs (KERNEL_DS);
2011
        ret = sys_nanosleep(&t, rmtp ? &t : NULL);
2012
        set_fs (old_fs);
2013
        if (rmtp && ret == -EINTR) {
2014
                if (__put_user (t.tv_sec, &rmtp->tv_sec) ||
2015
                    __put_user (t.tv_nsec, &rmtp->tv_nsec))
2016
                        return -EFAULT;
2017
        }
2018
        return ret;
2019
}
2020
 
2021
extern asmlinkage int sys_sigprocmask(int how, old_sigset_t *set, old_sigset_t *oset);
2022
 
2023
asmlinkage int sys32_sigprocmask(int how, old_sigset_t32 *set, old_sigset_t32 *oset)
2024
{
2025
        old_sigset_t s;
2026
        int ret;
2027
        mm_segment_t old_fs = get_fs();
2028
 
2029
        if (set && get_user (s, set)) return -EFAULT;
2030
        set_fs (KERNEL_DS);
2031
        ret = sys_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL);
2032
        set_fs (old_fs);
2033
        if (ret) return ret;
2034
        if (oset && put_user (s, oset)) return -EFAULT;
2035
        return 0;
2036
}
2037
 
2038
extern asmlinkage int sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, size_t sigsetsize);
2039
 
2040
asmlinkage int sys32_rt_sigprocmask(int how, sigset_t32 *set, sigset_t32 *oset, __kernel_size_t32 sigsetsize)
2041
{
2042
        sigset_t s;
2043
        sigset_t32 s32;
2044
        int ret;
2045
        mm_segment_t old_fs = get_fs();
2046
 
2047
        if (set) {
2048
                if (copy_from_user (&s32, set, sizeof(sigset_t32)))
2049
                        return -EFAULT;
2050
                switch (_NSIG_WORDS) {
2051
                case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);
2052
                case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32);
2053
                case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32);
2054
                case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
2055
                }
2056
        }
2057
        set_fs (KERNEL_DS);
2058
        ret = sys_rt_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL, sigsetsize);
2059
        set_fs (old_fs);
2060
        if (ret) return ret;
2061
        if (oset) {
2062
                switch (_NSIG_WORDS) {
2063
                case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
2064
                case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
2065
                case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
2066
                case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
2067
                }
2068
                if (copy_to_user (oset, &s32, sizeof(sigset_t32)))
2069
                        return -EFAULT;
2070
        }
2071
        return 0;
2072
}
2073
 
2074
extern asmlinkage int sys_sigpending(old_sigset_t *set);
2075
 
2076
asmlinkage int sys32_sigpending(old_sigset_t32 *set)
2077
{
2078
        old_sigset_t s;
2079
        int ret;
2080
        mm_segment_t old_fs = get_fs();
2081
 
2082
        set_fs (KERNEL_DS);
2083
        ret = sys_sigpending(&s);
2084
        set_fs (old_fs);
2085
        if (put_user (s, set)) return -EFAULT;
2086
        return ret;
2087
}
2088
 
2089
extern asmlinkage int sys_rt_sigpending(sigset_t *set, size_t sigsetsize);
2090
 
2091
asmlinkage int sys32_rt_sigpending(sigset_t32 *set, __kernel_size_t32 sigsetsize)
2092
{
2093
        sigset_t s;
2094
        sigset_t32 s32;
2095
        int ret;
2096
        mm_segment_t old_fs = get_fs();
2097
 
2098
        set_fs (KERNEL_DS);
2099
        ret = sys_rt_sigpending(&s, sigsetsize);
2100
        set_fs (old_fs);
2101
        if (!ret) {
2102
                switch (_NSIG_WORDS) {
2103
                case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
2104
                case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
2105
                case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
2106
                case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
2107
                }
2108
                if (copy_to_user (set, &s32, sizeof(sigset_t32)))
2109
                        return -EFAULT;
2110
        }
2111
        return ret;
2112
}
2113
 
2114
asmlinkage int
2115
sys32_rt_sigtimedwait(sigset_t32 *uthese, siginfo_t32 *uinfo,
2116
                      struct timespec32 *uts, __kernel_size_t32 sigsetsize)
2117
{
2118
        int ret, sig;
2119
        sigset_t these;
2120
        sigset_t32 these32;
2121
        struct timespec ts;
2122
        siginfo_t info;
2123
        long timeout = 0;
2124
 
2125
        /* XXX: Don't preclude handling different sized sigset_t's.  */
2126
        if (sigsetsize != sizeof(sigset_t))
2127
                return -EINVAL;
2128
 
2129
        if (copy_from_user (&these32, uthese, sizeof(sigset_t32)))
2130
                return -EFAULT;
2131
 
2132
        switch (_NSIG_WORDS) {
2133
        case 4: these.sig[3] = these32.sig[6] | (((long)these32.sig[7]) << 32);
2134
        case 3: these.sig[2] = these32.sig[4] | (((long)these32.sig[5]) << 32);
2135
        case 2: these.sig[1] = these32.sig[2] | (((long)these32.sig[3]) << 32);
2136
        case 1: these.sig[0] = these32.sig[0] | (((long)these32.sig[1]) << 32);
2137
        }
2138
 
2139
        /*
2140
         * Invert the set of allowed signals to get those we
2141
         * want to block.
2142
         */
2143
        sigdelsetmask(&these, sigmask(SIGKILL)|sigmask(SIGSTOP));
2144
        signotset(&these);
2145
 
2146
        if (uts) {
2147
                if (get_user (ts.tv_sec, &uts->tv_sec) ||
2148
                    get_user (ts.tv_nsec, &uts->tv_nsec))
2149
                        return -EINVAL;
2150
                if (ts.tv_nsec >= 1000000000L || ts.tv_nsec < 0
2151
                    || ts.tv_sec < 0)
2152
                        return -EINVAL;
2153
        }
2154
 
2155
        spin_lock_irq(&current->sigmask_lock);
2156
        sig = dequeue_signal(&these, &info);
2157
        if (!sig) {
2158
                timeout = MAX_SCHEDULE_TIMEOUT;
2159
                if (uts)
2160
                        timeout = (timespec_to_jiffies(&ts)
2161
                                   + (ts.tv_sec || ts.tv_nsec));
2162
 
2163
                current->state = TASK_INTERRUPTIBLE;
2164
                timeout = schedule_timeout(timeout);
2165
 
2166
                if (timeout) {
2167
                        /* None ready -- temporarily unblock those we're
2168
                         * interested while we are sleeping in so that we'll
2169
                         * be awakened when they arrive.  */
2170
                        sigset_t oldblocked = current->blocked;
2171
                        sigandsets(&current->blocked, &current->blocked, &these);
2172
                        recalc_sigpending(current);
2173
                        spin_unlock_irq(&current->sigmask_lock);
2174
 
2175
                        current->state = TASK_INTERRUPTIBLE;
2176
                        timeout = schedule_timeout(timeout);
2177
 
2178
                        spin_lock_irq(&current->sigmask_lock);
2179
                        sig = dequeue_signal(&these, &info);
2180
                        current->blocked = oldblocked;
2181
                        recalc_sigpending(current);
2182
                }
2183
        }
2184
        spin_unlock_irq(&current->sigmask_lock);
2185
 
2186
        if (sig) {
2187
                ret = sig;
2188
                if (uinfo) {
2189
                        if (copy_siginfo_to_user32(uinfo, &info))
2190
                                ret = -EFAULT;
2191
                }
2192
        } else {
2193
                ret = -EAGAIN;
2194
                if (timeout)
2195
                        ret = -EINTR;
2196
        }
2197
 
2198
        return ret;
2199
}
2200
 
2201
extern asmlinkage int
2202
sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo);
2203
 
2204
asmlinkage int
2205
sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 *uinfo)
2206
{
2207
        siginfo_t info;
2208
        int ret;
2209
        mm_segment_t old_fs = get_fs();
2210
 
2211
        if (copy_from_user (&info, uinfo, 3*sizeof(int)) ||
2212
            copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE))
2213
                return -EFAULT;
2214
        set_fs (KERNEL_DS);
2215
        ret = sys_rt_sigqueueinfo(pid, sig, &info);
2216
        set_fs (old_fs);
2217
        return ret;
2218
}
2219
 
2220
struct tms32 {
2221
        __kernel_clock_t32 tms_utime;
2222
        __kernel_clock_t32 tms_stime;
2223
        __kernel_clock_t32 tms_cutime;
2224
        __kernel_clock_t32 tms_cstime;
2225
};
2226
 
2227
extern asmlinkage long sys_times(struct tms * tbuf);
2228
 
2229
asmlinkage long sys32_times(struct tms32 *tbuf)
2230
{
2231
        struct tms t;
2232
        long ret;
2233
        mm_segment_t old_fs = get_fs ();
2234
        int err;
2235
 
2236
        set_fs (KERNEL_DS);
2237
        ret = sys_times(tbuf ? &t : NULL);
2238
        set_fs (old_fs);
2239
        if (tbuf) {
2240
                err = put_user (t.tms_utime, &tbuf->tms_utime);
2241
                err |= __put_user (t.tms_stime, &tbuf->tms_stime);
2242
                err |= __put_user (t.tms_cutime, &tbuf->tms_cutime);
2243
                err |= __put_user (t.tms_cstime, &tbuf->tms_cstime);
2244
                if (err)
2245
                        ret = -EFAULT;
2246
        }
2247
        return ret;
2248
}
2249
 
2250
#define RLIM_INFINITY32 0x7fffffff
2251
#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)
2252
 
2253
struct rlimit32 {
2254
        u32     rlim_cur;
2255
        u32     rlim_max;
2256
};
2257
 
2258
extern asmlinkage int sys_getrlimit(unsigned int resource, struct rlimit *rlim);
2259
 
2260
asmlinkage int sys32_getrlimit(unsigned int resource, struct rlimit32 *rlim)
2261
{
2262
        struct rlimit r;
2263
        int ret;
2264
        mm_segment_t old_fs = get_fs ();
2265
 
2266
        set_fs (KERNEL_DS);
2267
        ret = sys_getrlimit(resource, &r);
2268
        set_fs (old_fs);
2269
        if (!ret) {
2270
                ret = put_user (RESOURCE32(r.rlim_cur), &rlim->rlim_cur);
2271
                ret |= __put_user (RESOURCE32(r.rlim_max), &rlim->rlim_max);
2272
        }
2273
        return ret;
2274
}
2275
 
2276
extern asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim);
2277
 
2278
asmlinkage int sys32_setrlimit(unsigned int resource, struct rlimit32 *rlim)
2279
{
2280
        struct rlimit r;
2281
        int ret;
2282
        mm_segment_t old_fs = get_fs ();
2283
 
2284
        if (resource >= RLIM_NLIMITS) return -EINVAL;
2285
        if (get_user (r.rlim_cur, &rlim->rlim_cur) ||
2286
            __get_user (r.rlim_max, &rlim->rlim_max))
2287
                return -EFAULT;
2288
        if (r.rlim_cur == RLIM_INFINITY32)
2289
                r.rlim_cur = RLIM_INFINITY;
2290
        if (r.rlim_max == RLIM_INFINITY32)
2291
                r.rlim_max = RLIM_INFINITY;
2292
        set_fs (KERNEL_DS);
2293
        ret = sys_setrlimit(resource, &r);
2294
        set_fs (old_fs);
2295
        return ret;
2296
}
2297
 
2298
extern asmlinkage int sys_getrusage(int who, struct rusage *ru);
2299
 
2300
asmlinkage int sys32_getrusage(int who, struct rusage32 *ru)
2301
{
2302
        struct rusage r;
2303
        int ret;
2304
        mm_segment_t old_fs = get_fs();
2305
 
2306
        set_fs (KERNEL_DS);
2307
        ret = sys_getrusage(who, &r);
2308
        set_fs (old_fs);
2309
        if (put_rusage (ru, &r)) return -EFAULT;
2310
        return ret;
2311
}
2312
 
2313
/* XXX This really belongs in some header file... -DaveM */
2314
#define MAX_SOCK_ADDR   128             /* 108 for Unix domain - 
2315
                                           16 for IP, 16 for IPX,
2316
                                           24 for IPv6,
2317
                                           about 80 for AX.25 */
2318
 
2319
extern struct socket *sockfd_lookup(int fd, int *err);
2320
 
2321
/* XXX This as well... */
2322
extern __inline__ void sockfd_put(struct socket *sock)
2323
{
2324
        fput(sock->file);
2325
}
2326
 
2327
struct msghdr32 {
2328
        u32               msg_name;
2329
        int               msg_namelen;
2330
        u32               msg_iov;
2331
        __kernel_size_t32 msg_iovlen;
2332
        u32               msg_control;
2333
        __kernel_size_t32 msg_controllen;
2334
        unsigned          msg_flags;
2335
};
2336
 
2337
struct cmsghdr32 {
2338
        __kernel_size_t32 cmsg_len;
2339
        int               cmsg_level;
2340
        int               cmsg_type;
2341
};
2342
 
2343
/* Bleech... */
2344
#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen))
2345
#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen))
2346
 
2347
#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) )
2348
 
2349
#define CMSG32_DATA(cmsg)       ((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32))))
2350
#define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len))
2351
#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len))
2352
 
2353
#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \
2354
                                    (struct cmsghdr32 *)(ctl) : \
2355
                                    (struct cmsghdr32 *)NULL)
2356
#define CMSG32_FIRSTHDR(msg)    __CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
2357
 
2358
__inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size,
2359
                                              struct cmsghdr32 *__cmsg, int __cmsg_len)
2360
{
2361
        struct cmsghdr32 * __ptr;
2362
 
2363
        __ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) +
2364
                                     CMSG32_ALIGN(__cmsg_len));
2365
        if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size)
2366
                return NULL;
2367
 
2368
        return __ptr;
2369
}
2370
 
2371
__inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg,
2372
                                            struct cmsghdr32 *__cmsg,
2373
                                            int __cmsg_len)
2374
{
2375
        return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen,
2376
                               __cmsg, __cmsg_len);
2377
}
2378
 
2379
static inline int iov_from_user32_to_kern(struct iovec *kiov,
2380
                                          struct iovec32 *uiov32,
2381
                                          int niov)
2382
{
2383
        int tot_len = 0;
2384
 
2385
        while(niov > 0) {
2386
                u32 len, buf;
2387
 
2388
                if(get_user(len, &uiov32->iov_len) ||
2389
                   get_user(buf, &uiov32->iov_base)) {
2390
                        tot_len = -EFAULT;
2391
                        break;
2392
                }
2393
                tot_len += len;
2394
                kiov->iov_base = (void *)A(buf);
2395
                kiov->iov_len = (__kernel_size_t) len;
2396
                uiov32++;
2397
                kiov++;
2398
                niov--;
2399
        }
2400
        return tot_len;
2401
}
2402
 
2403
static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg,
2404
                                             struct msghdr32 *umsg)
2405
{
2406
        u32 tmp1, tmp2, tmp3;
2407
        int err;
2408
 
2409
        err = get_user(tmp1, &umsg->msg_name);
2410
        err |= __get_user(tmp2, &umsg->msg_iov);
2411
        err |= __get_user(tmp3, &umsg->msg_control);
2412
        if (err)
2413
                return -EFAULT;
2414
 
2415
        kmsg->msg_name = (void *)A(tmp1);
2416
        kmsg->msg_iov = (struct iovec *)A(tmp2);
2417
        kmsg->msg_control = (void *)A(tmp3);
2418
 
2419
        err = get_user(kmsg->msg_namelen, &umsg->msg_namelen);
2420
        err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen);
2421
        err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen);
2422
        err |= get_user(kmsg->msg_flags, &umsg->msg_flags);
2423
 
2424
        return err;
2425
}
2426
 
2427
/* I've named the args so it is easy to tell whose space the pointers are in. */
2428
static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov,
2429
                          char *kern_address, int mode)
2430
{
2431
        int tot_len;
2432
 
2433
        if(kern_msg->msg_namelen) {
2434
                if(mode==VERIFY_READ) {
2435
                        int err = move_addr_to_kernel(kern_msg->msg_name,
2436
                                                      kern_msg->msg_namelen,
2437
                                                      kern_address);
2438
                        if(err < 0)
2439
                                return err;
2440
                }
2441
                kern_msg->msg_name = kern_address;
2442
        } else
2443
                kern_msg->msg_name = NULL;
2444
 
2445
        if(kern_msg->msg_iovlen > UIO_FASTIOV) {
2446
                kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec),
2447
                                   GFP_KERNEL);
2448
                if(!kern_iov)
2449
                        return -ENOMEM;
2450
        }
2451
 
2452
        tot_len = iov_from_user32_to_kern(kern_iov,
2453
                                          (struct iovec32 *)kern_msg->msg_iov,
2454
                                          kern_msg->msg_iovlen);
2455
        if(tot_len >= 0)
2456
                kern_msg->msg_iov = kern_iov;
2457
        else if(kern_msg->msg_iovlen > UIO_FASTIOV)
2458
                kfree(kern_iov);
2459
 
2460
        return tot_len;
2461
}
2462
 
2463
/* There is a lot of hair here because the alignment rules (and
2464
 * thus placement) of cmsg headers and length are different for
2465
 * 32-bit apps.  -DaveM
2466
 */
2467
static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg,
2468
                                       unsigned char *stackbuf, int stackbuf_size)
2469
{
2470
        struct cmsghdr32 *ucmsg;
2471
        struct cmsghdr *kcmsg, *kcmsg_base;
2472
        __kernel_size_t32 ucmlen;
2473
        __kernel_size_t kcmlen, tmp;
2474
 
2475
        kcmlen = 0;
2476
        kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
2477
        ucmsg = CMSG32_FIRSTHDR(kmsg);
2478
        while(ucmsg != NULL) {
2479
                if(get_user(ucmlen, &ucmsg->cmsg_len))
2480
                        return -EFAULT;
2481
 
2482
                /* Catch bogons. */
2483
                if(CMSG32_ALIGN(ucmlen) <
2484
                   CMSG32_ALIGN(sizeof(struct cmsghdr32)))
2485
                        return -EINVAL;
2486
                if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control)
2487
                                   + ucmlen) > kmsg->msg_controllen)
2488
                        return -EINVAL;
2489
 
2490
                tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
2491
                       CMSG_ALIGN(sizeof(struct cmsghdr)));
2492
                kcmlen += tmp;
2493
                ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
2494
        }
2495
        if(kcmlen == 0)
2496
                return -EINVAL;
2497
 
2498
        /* The kcmlen holds the 64-bit version of the control length.
2499
         * It may not be modified as we do not stick it into the kmsg
2500
         * until we have successfully copied over all of the data
2501
         * from the user.
2502
         */
2503
        if(kcmlen > stackbuf_size)
2504
                kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL);
2505
        if(kcmsg == NULL)
2506
                return -ENOBUFS;
2507
 
2508
        /* Now copy them over neatly. */
2509
        memset(kcmsg, 0, kcmlen);
2510
        ucmsg = CMSG32_FIRSTHDR(kmsg);
2511
        while(ucmsg != NULL) {
2512
                __get_user(ucmlen, &ucmsg->cmsg_len);
2513
                tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
2514
                       CMSG_ALIGN(sizeof(struct cmsghdr)));
2515
                kcmsg->cmsg_len = tmp;
2516
                __get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);
2517
                __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);
2518
 
2519
                /* Copy over the data. */
2520
                if(copy_from_user(CMSG_DATA(kcmsg),
2521
                                  CMSG32_DATA(ucmsg),
2522
                                  (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))))
2523
                        goto out_free_efault;
2524
 
2525
                /* Advance. */
2526
                kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
2527
                ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
2528
        }
2529
 
2530
        /* Ok, looks like we made it.  Hook it up and return success. */
2531
        kmsg->msg_control = kcmsg_base;
2532
        kmsg->msg_controllen = kcmlen;
2533
        return 0;
2534
 
2535
out_free_efault:
2536
        if(kcmsg_base != (struct cmsghdr *)stackbuf)
2537
                kfree(kcmsg_base);
2538
        return -EFAULT;
2539
}
2540
 
2541
static void put_cmsg32(struct msghdr *kmsg, int level, int type,
2542
                       int len, void *data)
2543
{
2544
        struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
2545
        struct cmsghdr32 cmhdr;
2546
        int cmlen = CMSG32_LEN(len);
2547
 
2548
        if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) {
2549
                kmsg->msg_flags |= MSG_CTRUNC;
2550
                return;
2551
        }
2552
 
2553
        if(kmsg->msg_controllen < cmlen) {
2554
                kmsg->msg_flags |= MSG_CTRUNC;
2555
                cmlen = kmsg->msg_controllen;
2556
        }
2557
        cmhdr.cmsg_level = level;
2558
        cmhdr.cmsg_type = type;
2559
        cmhdr.cmsg_len = cmlen;
2560
 
2561
        if(copy_to_user(cm, &cmhdr, sizeof cmhdr))
2562
                return;
2563
        if(copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32)))
2564
                return;
2565
        cmlen = CMSG32_SPACE(len);
2566
        kmsg->msg_control += cmlen;
2567
        kmsg->msg_controllen -= cmlen;
2568
}
2569
 
2570
static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm)
2571
{
2572
        struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
2573
        int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int);
2574
        int fdnum = scm->fp->count;
2575
        struct file **fp = scm->fp->fp;
2576
        int *cmfptr;
2577
        int err = 0, i;
2578
 
2579
        if (fdnum < fdmax)
2580
                fdmax = fdnum;
2581
 
2582
        for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) {
2583
                int new_fd;
2584
                err = get_unused_fd();
2585
                if (err < 0)
2586
                        break;
2587
                new_fd = err;
2588
                err = put_user(new_fd, cmfptr);
2589
                if (err) {
2590
                        put_unused_fd(new_fd);
2591
                        break;
2592
                }
2593
                /* Bump the usage count and install the file. */
2594
                get_file(fp[i]);
2595
                fd_install(new_fd, fp[i]);
2596
        }
2597
 
2598
        if (i > 0) {
2599
                int cmlen = CMSG32_LEN(i * sizeof(int));
2600
                if (!err)
2601
                        err = put_user(SOL_SOCKET, &cm->cmsg_level);
2602
                if (!err)
2603
                        err = put_user(SCM_RIGHTS, &cm->cmsg_type);
2604
                if (!err)
2605
                        err = put_user(cmlen, &cm->cmsg_len);
2606
                if (!err) {
2607
                        cmlen = CMSG32_SPACE(i * sizeof(int));
2608
                        kmsg->msg_control += cmlen;
2609
                        kmsg->msg_controllen -= cmlen;
2610
                }
2611
        }
2612
        if (i < fdnum)
2613
                kmsg->msg_flags |= MSG_CTRUNC;
2614
 
2615
        /*
2616
         * All of the files that fit in the message have had their
2617
         * usage counts incremented, so we just free the list.
2618
         */
2619
        __scm_destroy(scm);
2620
}
2621
 
2622
/* In these cases we (currently) can just copy to data over verbatim
2623
 * because all CMSGs created by the kernel have well defined types which
2624
 * have the same layout in both the 32-bit and 64-bit API.  One must add
2625
 * some special cased conversions here if we start sending control messages
2626
 * with incompatible types.
2627
 *
2628
 * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after
2629
 * we do our work.  The remaining cases are:
2630
 *
2631
 * SOL_IP       IP_PKTINFO      struct in_pktinfo       32-bit clean
2632
 *              IP_TTL          int                     32-bit clean
2633
 *              IP_TOS          __u8                    32-bit clean
2634
 *              IP_RECVOPTS     variable length         32-bit clean
2635
 *              IP_RETOPTS      variable length         32-bit clean
2636
 *              (these last two are clean because the types are defined
2637
 *               by the IPv4 protocol)
2638
 *              IP_RECVERR      struct sock_extended_err +
2639
 *                              struct sockaddr_in      32-bit clean
2640
 * SOL_IPV6     IPV6_RECVERR    struct sock_extended_err +
2641
 *                              struct sockaddr_in6     32-bit clean
2642
 *              IPV6_PKTINFO    struct in6_pktinfo      32-bit clean
2643
 *              IPV6_HOPLIMIT   int                     32-bit clean
2644
 *              IPV6_FLOWINFO   u32                     32-bit clean
2645
 *              IPV6_HOPOPTS    ipv6 hop exthdr         32-bit clean
2646
 *              IPV6_DSTOPTS    ipv6 dst exthdr(s)      32-bit clean
2647
 *              IPV6_RTHDR      ipv6 routing exthdr     32-bit clean
2648
 *              IPV6_AUTHHDR    ipv6 auth exthdr        32-bit clean
2649
 */
2650
static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr)
2651
{
2652
        unsigned char *workbuf, *wp;
2653
        unsigned long bufsz, space_avail;
2654
        struct cmsghdr *ucmsg;
2655
 
2656
        bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr;
2657
        space_avail = kmsg->msg_controllen + bufsz;
2658
        wp = workbuf = kmalloc(bufsz, GFP_KERNEL);
2659
        if(workbuf == NULL)
2660
                goto fail;
2661
 
2662
        /* To make this more sane we assume the kernel sends back properly
2663
         * formatted control messages.  Because of how the kernel will truncate
2664
         * the cmsg_len for MSG_TRUNC cases, we need not check that case either.
2665
         */
2666
        ucmsg = (struct cmsghdr *) orig_cmsg_uptr;
2667
        while(((unsigned long)ucmsg) <=
2668
              (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) {
2669
                struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp;
2670
                int clen64, clen32;
2671
 
2672
                /* UCMSG is the 64-bit format CMSG entry in user-space.
2673
                 * KCMSG32 is within the kernel space temporary buffer
2674
                 * we use to convert into a 32-bit style CMSG.
2675
                 */
2676
                __get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len);
2677
                __get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level);
2678
                __get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type);
2679
 
2680
                clen64 = kcmsg32->cmsg_len;
2681
                if (kcmsg32->cmsg_level == SOL_SOCKET &&
2682
                        kcmsg32->cmsg_type == SO_TIMESTAMP) {
2683
                        struct timeval tv;
2684
                        struct timeval32 *tv32;
2685
 
2686
                        if (clen64 != CMSG_LEN(sizeof(struct timeval))) {
2687
                                kfree(workbuf);
2688
                                goto fail;
2689
                        }
2690
 
2691
                        copy_from_user(&tv, CMSG_DATA(ucmsg), sizeof(tv));
2692
                        tv32 = (struct timeval32 *)CMSG32_DATA(kcmsg32);
2693
                        tv32->tv_sec = tv.tv_sec;
2694
                        tv32->tv_usec = tv.tv_usec;
2695
                        clen32 = sizeof(*tv32) +
2696
                                  CMSG32_ALIGN(sizeof(struct cmsghdr32));
2697
                } else {
2698
                        copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg),
2699
                                       clen64 - CMSG_ALIGN(sizeof(*ucmsg)));
2700
                        clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) +
2701
                                  CMSG32_ALIGN(sizeof(struct cmsghdr32)));
2702
                }
2703
                kcmsg32->cmsg_len = clen32;
2704
 
2705
                ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64));
2706
                wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32));
2707
        }
2708
 
2709
        /* Copy back fixed up data, and adjust pointers. */
2710
        bufsz = (wp - workbuf);
2711
        copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz);
2712
 
2713
        kmsg->msg_control = (struct cmsghdr *)
2714
                (((char *)orig_cmsg_uptr) + bufsz);
2715
        kmsg->msg_controllen = space_avail - bufsz;
2716
 
2717
        kfree(workbuf);
2718
        return;
2719
 
2720
fail:
2721
        /* If we leave the 64-bit format CMSG chunks in there,
2722
         * the application could get confused and crash.  So to
2723
         * ensure greater recovery, we report no CMSGs.
2724
         */
2725
        kmsg->msg_controllen += bufsz;
2726
        kmsg->msg_control = (void *) orig_cmsg_uptr;
2727
}
2728
 
2729
asmlinkage int sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags)
2730
{
2731
        struct socket *sock;
2732
        char address[MAX_SOCK_ADDR];
2733
        struct iovec iov[UIO_FASTIOV];
2734
        unsigned char ctl[sizeof(struct cmsghdr) + 20];
2735
        unsigned char *ctl_buf = ctl;
2736
        struct msghdr kern_msg;
2737
        int err, total_len;
2738
 
2739
        if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
2740
                return -EFAULT;
2741
        if(kern_msg.msg_iovlen > UIO_MAXIOV)
2742
                return -EINVAL;
2743
        err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ);
2744
        if (err < 0)
2745
                goto out;
2746
        total_len = err;
2747
 
2748
        if(kern_msg.msg_controllen) {
2749
                err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl));
2750
                if(err)
2751
                        goto out_freeiov;
2752
                ctl_buf = kern_msg.msg_control;
2753
        }
2754
        kern_msg.msg_flags = user_flags;
2755
 
2756
        sock = sockfd_lookup(fd, &err);
2757
        if (sock != NULL) {
2758
                if (sock->file->f_flags & O_NONBLOCK)
2759
                        kern_msg.msg_flags |= MSG_DONTWAIT;
2760
                err = sock_sendmsg(sock, &kern_msg, total_len);
2761
                sockfd_put(sock);
2762
        }
2763
 
2764
        /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */
2765
        if(ctl_buf != ctl)
2766
                kfree(ctl_buf);
2767
out_freeiov:
2768
        if(kern_msg.msg_iov != iov)
2769
                kfree(kern_msg.msg_iov);
2770
out:
2771
        return err;
2772
}
2773
 
2774
asmlinkage int sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int user_flags)
2775
{
2776
        struct iovec iovstack[UIO_FASTIOV];
2777
        struct msghdr kern_msg;
2778
        char addr[MAX_SOCK_ADDR];
2779
        struct socket *sock;
2780
        struct iovec *iov = iovstack;
2781
        struct sockaddr *uaddr;
2782
        int *uaddr_len;
2783
        unsigned long cmsg_ptr;
2784
        int err, total_len, len = 0;
2785
 
2786
        if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
2787
                return -EFAULT;
2788
        if(kern_msg.msg_iovlen > UIO_MAXIOV)
2789
                return -EINVAL;
2790
 
2791
        uaddr = kern_msg.msg_name;
2792
        uaddr_len = &user_msg->msg_namelen;
2793
        err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE);
2794
        if (err < 0)
2795
                goto out;
2796
        total_len = err;
2797
 
2798
        cmsg_ptr = (unsigned long) kern_msg.msg_control;
2799
        kern_msg.msg_flags = 0;
2800
 
2801
        sock = sockfd_lookup(fd, &err);
2802
        if (sock != NULL) {
2803
                struct scm_cookie scm;
2804
 
2805
                if (sock->file->f_flags & O_NONBLOCK)
2806
                        user_flags |= MSG_DONTWAIT;
2807
                memset(&scm, 0, sizeof(scm));
2808
                err = sock->ops->recvmsg(sock, &kern_msg, total_len,
2809
                                         user_flags, &scm);
2810
                if(err >= 0) {
2811
                        len = err;
2812
                        if(!kern_msg.msg_control) {
2813
                                if(sock->passcred || scm.fp)
2814
                                        kern_msg.msg_flags |= MSG_CTRUNC;
2815
                                if(scm.fp)
2816
                                        __scm_destroy(&scm);
2817
                        } else {
2818
                                /* If recvmsg processing itself placed some
2819
                                 * control messages into user space, it's is
2820
                                 * using 64-bit CMSG processing, so we need
2821
                                 * to fix it up before we tack on more stuff.
2822
                                 */
2823
                                if((unsigned long) kern_msg.msg_control != cmsg_ptr)
2824
                                        cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr);
2825
 
2826
                                /* Wheee... */
2827
                                if(sock->passcred)
2828
                                        put_cmsg32(&kern_msg,
2829
                                                   SOL_SOCKET, SCM_CREDENTIALS,
2830
                                                   sizeof(scm.creds), &scm.creds);
2831
                                if(scm.fp != NULL)
2832
                                        scm_detach_fds32(&kern_msg, &scm);
2833
                        }
2834
                }
2835
                sockfd_put(sock);
2836
        }
2837
 
2838
        if(uaddr != NULL && err >= 0)
2839
                err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len);
2840
        if(cmsg_ptr != 0 && err >= 0) {
2841
                unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control);
2842
                __kernel_size_t32 uclen = (__kernel_size_t32) (ucmsg_ptr - cmsg_ptr);
2843
                err |= __put_user(uclen, &user_msg->msg_controllen);
2844
        }
2845
        if(err >= 0)
2846
                err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags);
2847
        if(kern_msg.msg_iov != iov)
2848
                kfree(kern_msg.msg_iov);
2849
out:
2850
        if(err < 0)
2851
                return err;
2852
        return len;
2853
}
2854
 
2855
extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
2856
                                     char *optval, int optlen);
2857
 
2858
static int do_netfilter_replace(int fd, int level, int optname,
2859
                                char *optval, int optlen)
2860
{
2861
        struct ipt_replace32 {
2862
                char name[IPT_TABLE_MAXNAMELEN];
2863
                __u32 valid_hooks;
2864
                __u32 num_entries;
2865
                __u32 size;
2866
                __u32 hook_entry[NF_IP_NUMHOOKS];
2867
                __u32 underflow[NF_IP_NUMHOOKS];
2868
                __u32 num_counters;
2869
                __u32 counters;
2870
                struct ipt_entry entries[0];
2871
        } *repl32 = (struct ipt_replace32 *)optval;
2872
        struct ipt_replace *krepl;
2873
        struct ipt_counters *counters32;
2874
        __u32 origsize;
2875
        unsigned int kreplsize, kcountersize;
2876
        mm_segment_t old_fs;
2877
        int ret;
2878
 
2879
        if (optlen < sizeof(repl32))
2880
                return -EINVAL;
2881
 
2882
        if (copy_from_user(&origsize,
2883
                        &repl32->size,
2884
                        sizeof(origsize)))
2885
                return -EFAULT;
2886
 
2887
        kreplsize = sizeof(*krepl) + origsize;
2888
        kcountersize = krepl->num_counters * sizeof(struct ipt_counters);
2889
 
2890
        /* Hack: Causes ipchains to give correct error msg --RR */
2891
        if (optlen != kreplsize)
2892
                return -ENOPROTOOPT;
2893
 
2894
        krepl = (struct ipt_replace *)kmalloc(kreplsize, GFP_KERNEL);
2895
        if (krepl == NULL)
2896
                return -ENOMEM;
2897
 
2898
        if (copy_from_user(krepl, optval, kreplsize)) {
2899
                kfree(krepl);
2900
                return -EFAULT;
2901
        }
2902
 
2903
        counters32 = (struct ipt_counters *)AA(
2904
                ((struct ipt_replace32 *)krepl)->counters);
2905
 
2906
        kcountersize = krepl->num_counters * sizeof(struct ipt_counters);
2907
        krepl->counters = (struct ipt_counters *)kmalloc(
2908
                                        kcountersize, GFP_KERNEL);
2909
        if (krepl->counters == NULL) {
2910
                kfree(krepl);
2911
                return -ENOMEM;
2912
        }
2913
 
2914
        old_fs = get_fs();
2915
        set_fs(KERNEL_DS);
2916
        ret = sys_setsockopt(fd, level, optname,
2917
                             (char *)krepl, kreplsize);
2918
        set_fs(old_fs);
2919
 
2920
        if (ret == 0 &&
2921
                copy_to_user(counters32, krepl->counters, kcountersize))
2922
                        ret = -EFAULT;
2923
 
2924
        kfree(krepl->counters);
2925
        kfree(krepl);
2926
 
2927
        return ret;
2928
}
2929
 
2930
static int do_set_attach_filter(int fd, int level, int optname,
2931
                                char *optval, int optlen)
2932
{
2933
        struct sock_fprog32 {
2934
                __u16 len;
2935
                __u32 filter;
2936
        } *fprog32 = (struct sock_fprog32 *)optval;
2937
        struct sock_fprog kfprog;
2938
        struct sock_filter *kfilter;
2939
        unsigned int fsize;
2940
        mm_segment_t old_fs;
2941
        __u32 uptr;
2942
        int ret;
2943
 
2944
        if (get_user(kfprog.len, &fprog32->len) ||
2945
            __get_user(uptr, &fprog32->filter))
2946
                return -EFAULT;
2947
 
2948
        kfprog.filter = (struct sock_filter *)A(uptr);
2949
        fsize = kfprog.len * sizeof(struct sock_filter);
2950
 
2951
        kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL);
2952
        if (kfilter == NULL)
2953
                return -ENOMEM;
2954
 
2955
        if (copy_from_user(kfilter, kfprog.filter, fsize)) {
2956
                kfree(kfilter);
2957
                return -EFAULT;
2958
        }
2959
 
2960
        kfprog.filter = kfilter;
2961
 
2962
        old_fs = get_fs();
2963
        set_fs(KERNEL_DS);
2964
        ret = sys_setsockopt(fd, level, optname,
2965
                             (char *)&kfprog, sizeof(kfprog));
2966
        set_fs(old_fs);
2967
 
2968
        kfree(kfilter);
2969
 
2970
        return ret;
2971
}
2972
 
2973
static int do_set_sock_timeout(int fd, int level, int optname, char *optval, int optlen)
2974
{
2975
        struct timeval32 *up = (struct timeval32 *) optval;
2976
        struct timeval ktime;
2977
        mm_segment_t old_fs;
2978
        int err;
2979
 
2980
        if (optlen < sizeof(*up))
2981
                return -EINVAL;
2982
        if (get_user(ktime.tv_sec, &up->tv_sec) ||
2983
            __get_user(ktime.tv_usec, &up->tv_usec))
2984
                return -EFAULT;
2985
        old_fs = get_fs();
2986
        set_fs(KERNEL_DS);
2987
        err = sys_setsockopt(fd, level, optname, (char *) &ktime, sizeof(ktime));
2988
        set_fs(old_fs);
2989
 
2990
        return err;
2991
}
2992
 
2993
asmlinkage int sys32_setsockopt(int fd, int level, int optname,
2994
                                char *optval, int optlen)
2995
{
2996
        if (optname == IPT_SO_SET_REPLACE)
2997
                return do_netfilter_replace(fd, level, optname,
2998
                                            optval, optlen);
2999
        if (optname == SO_ATTACH_FILTER)
3000
                return do_set_attach_filter(fd, level, optname,
3001
                                            optval, optlen);
3002
        if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
3003
                return do_set_sock_timeout(fd, level, optname, optval, optlen);
3004
 
3005
        return sys_setsockopt(fd, level, optname, optval, optlen);
3006
}
3007
 
3008
extern asmlinkage long sys_getsockopt(int fd, int level, int optname,
3009
                                      char *optval, int *optlen);
3010
 
3011
static int do_get_sock_timeout(int fd, int level, int optname, char *optval, int *optlen)
3012
{
3013
        struct timeval32 *up = (struct timeval32 *) optval;
3014
        struct timeval ktime;
3015
        mm_segment_t old_fs;
3016
        int len, err;
3017
 
3018
        if (get_user(len, optlen))
3019
                return -EFAULT;
3020
        if (len < sizeof(*up))
3021
                return -EINVAL;
3022
        len = sizeof(ktime);
3023
        old_fs = get_fs();
3024
        set_fs(KERNEL_DS);
3025
        err = sys_getsockopt(fd, level, optname, (char *) &ktime, &len);
3026
        set_fs(old_fs);
3027
 
3028
        if (!err) {
3029
                if (put_user(sizeof(*up), optlen) ||
3030
                    put_user(ktime.tv_sec, &up->tv_sec) ||
3031
                    __put_user(ktime.tv_usec, &up->tv_usec))
3032
                        err = -EFAULT;
3033
        }
3034
        return err;
3035
}
3036
 
3037
asmlinkage int sys32_getsockopt(int fd, int level, int optname,
3038
                                char *optval, int *optlen)
3039
{
3040
        if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
3041
                return do_get_sock_timeout(fd, level, optname, optval, optlen);
3042
        return sys_getsockopt(fd, level, optname, optval, optlen);
3043
}
3044
 
3045
extern void check_pending(int signum);
3046
 
3047
asmlinkage int sys32_sigaction (int sig, struct old_sigaction32 *act, struct old_sigaction32 *oact)
3048
{
3049
        struct k_sigaction new_ka, old_ka;
3050
        int ret;
3051
 
3052
        if(sig < 0) {
3053
                current->thread.flags |= SPARC_FLAG_NEWSIGNALS;
3054
                sig = -sig;
3055
        }
3056
 
3057
        if (act) {
3058
                old_sigset_t32 mask;
3059
 
3060
                ret = get_user((long)new_ka.sa.sa_handler, &act->sa_handler);
3061
                ret |= __get_user((long)new_ka.sa.sa_restorer, &act->sa_restorer);
3062
                ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
3063
                ret |= __get_user(mask, &act->sa_mask);
3064
                if (ret)
3065
                        return ret;
3066
                new_ka.ka_restorer = NULL;
3067
                siginitset(&new_ka.sa.sa_mask, mask);
3068
        }
3069
 
3070
        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
3071
 
3072
        if (!ret && oact) {
3073
                ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler);
3074
                ret |= __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer);
3075
                ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
3076
                ret |= __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
3077
        }
3078
 
3079
        return ret;
3080
}
3081
 
3082
asmlinkage int
3083
sys32_rt_sigaction(int sig, struct sigaction32 *act, struct sigaction32 *oact,
3084
                   void *restorer, __kernel_size_t32 sigsetsize)
3085
{
3086
        struct k_sigaction new_ka, old_ka;
3087
        int ret;
3088
        sigset_t32 set32;
3089
 
3090
        /* XXX: Don't preclude handling different sized sigset_t's.  */
3091
        if (sigsetsize != sizeof(sigset_t32))
3092
                return -EINVAL;
3093
 
3094
        /* All tasks which use RT signals (effectively) use
3095
         * new style signals.
3096
         */
3097
        current->thread.flags |= SPARC_FLAG_NEWSIGNALS;
3098
 
3099
        if (act) {
3100
                new_ka.ka_restorer = restorer;
3101
                ret = get_user((long)new_ka.sa.sa_handler, &act->sa_handler);
3102
                ret |= __copy_from_user(&set32, &act->sa_mask, sizeof(sigset_t32));
3103
                switch (_NSIG_WORDS) {
3104
                case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6] | (((long)set32.sig[7]) << 32);
3105
                case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4] | (((long)set32.sig[5]) << 32);
3106
                case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2] | (((long)set32.sig[3]) << 32);
3107
                case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0] | (((long)set32.sig[1]) << 32);
3108
                }
3109
                ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
3110
                ret |= __get_user((long)new_ka.sa.sa_restorer, &act->sa_restorer);
3111
                if (ret)
3112
                        return -EFAULT;
3113
        }
3114
 
3115
        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
3116
 
3117
        if (!ret && oact) {
3118
                switch (_NSIG_WORDS) {
3119
                case 4: set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32); set32.sig[6] = old_ka.sa.sa_mask.sig[3];
3120
                case 3: set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32); set32.sig[4] = old_ka.sa.sa_mask.sig[2];
3121
                case 2: set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32); set32.sig[2] = old_ka.sa.sa_mask.sig[1];
3122
                case 1: set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32); set32.sig[0] = old_ka.sa.sa_mask.sig[0];
3123
                }
3124
                ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler);
3125
                ret |= __copy_to_user(&oact->sa_mask, &set32, sizeof(sigset_t32));
3126
                ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
3127
                ret |= __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer);
3128
                if (ret)
3129
                        ret = -EFAULT;
3130
        }
3131
 
3132
        return ret;
3133
}
3134
 
3135
 
3136
/*
3137
 * count32() counts the number of arguments/envelopes
3138
 */
3139
static int count32(u32 * argv, int max)
3140
{
3141
        int i = 0;
3142
 
3143
        if (argv != NULL) {
3144
                for (;;) {
3145
                        u32 p; int error;
3146
 
3147
                        error = get_user(p,argv);
3148
                        if (error)
3149
                                return error;
3150
                        if (!p)
3151
                                break;
3152
                        argv++;
3153
                        if (++i > max)
3154
                                return -E2BIG;
3155
                }
3156
        }
3157
        return i;
3158
}
3159
 
3160
/*
3161
 * 'copy_string32()' copies argument/envelope strings from user
3162
 * memory to free pages in kernel mem. These are in a format ready
3163
 * to be put directly into the top of new user memory.
3164
 */
3165
static int copy_strings32(int argc, u32 * argv, struct linux_binprm *bprm)
3166
{
3167
        while (argc-- > 0) {
3168
                u32 str;
3169
                int len;
3170
                unsigned long pos;
3171
 
3172
                if (get_user(str, argv + argc) ||
3173
                    !str ||
3174
                    !(len = strnlen_user((char *)A(str), bprm->p)))
3175
                        return -EFAULT;
3176
 
3177
                if (bprm->p < len)
3178
                        return -E2BIG;
3179
 
3180
                bprm->p -= len;
3181
 
3182
                pos = bprm->p;
3183
                while (len) {
3184
                        char *kaddr;
3185
                        struct page *page;
3186
                        int offset, bytes_to_copy, new, err;
3187
 
3188
                        offset = pos % PAGE_SIZE;
3189
                        page = bprm->page[pos / PAGE_SIZE];
3190
                        new = 0;
3191
                        if (!page) {
3192
                                page = alloc_page(GFP_USER);
3193
                                bprm->page[pos / PAGE_SIZE] = page;
3194
                                if (!page)
3195
                                        return -ENOMEM;
3196
                                new = 1;
3197
                        }
3198
                        kaddr = kmap(page);
3199
 
3200
                        if (new && offset)
3201
                                memset(kaddr, 0, offset);
3202
                        bytes_to_copy = PAGE_SIZE - offset;
3203
                        if (bytes_to_copy > len) {
3204
                                bytes_to_copy = len;
3205
                                if (new)
3206
                                        memset(kaddr+offset+len, 0,
3207
                                               PAGE_SIZE-offset-len);
3208
                        }
3209
 
3210
                        err = copy_from_user(kaddr + offset, (char *)A(str),
3211
                                             bytes_to_copy);
3212
                        kunmap(page);
3213
 
3214
                        if (err)
3215
                                return -EFAULT;
3216
 
3217
                        pos += bytes_to_copy;
3218
                        str += bytes_to_copy;
3219
                        len -= bytes_to_copy;
3220
                }
3221
        }
3222
        return 0;
3223
}
3224
 
3225
/*
3226
 * sys32_execve() executes a new program.
3227
 */
3228
static inline int
3229
do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs)
3230
{
3231
        struct linux_binprm bprm;
3232
        struct file * file;
3233
        int retval;
3234
        int i;
3235
 
3236
        bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
3237
        memset(bprm.page, 0, MAX_ARG_PAGES * sizeof(bprm.page[0]));
3238
 
3239
        file = open_exec(filename);
3240
 
3241
        retval = PTR_ERR(file);
3242
        if (IS_ERR(file))
3243
                return retval;
3244
 
3245
        bprm.file = file;
3246
        bprm.filename = filename;
3247
        bprm.sh_bang = 0;
3248
        bprm.loader = 0;
3249
        bprm.exec = 0;
3250
        if ((bprm.argc = count32(argv, bprm.p / sizeof(u32))) < 0) {
3251
                allow_write_access(file);
3252
                fput(file);
3253
                return bprm.argc;
3254
        }
3255
        if ((bprm.envc = count32(envp, bprm.p / sizeof(u32))) < 0) {
3256
                allow_write_access(file);
3257
                fput(file);
3258
                return bprm.envc;
3259
        }
3260
 
3261
        retval = prepare_binprm(&bprm);
3262
        if (retval < 0)
3263
                goto out;
3264
 
3265
        retval = copy_strings_kernel(1, &bprm.filename, &bprm);
3266
        if (retval < 0)
3267
                goto out;
3268
 
3269
        bprm.exec = bprm.p;
3270
        retval = copy_strings32(bprm.envc, envp, &bprm);
3271
        if (retval < 0)
3272
                goto out;
3273
 
3274
        retval = copy_strings32(bprm.argc, argv, &bprm);
3275
        if (retval < 0)
3276
                goto out;
3277
 
3278
        retval = search_binary_handler(&bprm, regs);
3279
        if (retval >= 0)
3280
                /* execve success */
3281
                return retval;
3282
 
3283
out:
3284
        /* Something went wrong, return the inode and free the argument pages*/
3285
        allow_write_access(bprm.file);
3286
        if (bprm.file)
3287
                fput(bprm.file);
3288
 
3289
        for (i=0 ; i<MAX_ARG_PAGES ; i++)
3290
                if (bprm.page[i])
3291
                        __free_page(bprm.page[i]);
3292
 
3293
        return retval;
3294
}
3295
 
3296
/*
3297
 * sparc32_execve() executes a new program after the asm stub has set
3298
 * things up for us.  This should basically do what I want it to.
3299
 */
3300
asmlinkage int sparc32_execve(struct pt_regs *regs)
3301
{
3302
        int error, base = 0;
3303
        char *filename;
3304
 
3305
        /* User register window flush is done by entry.S */
3306
 
3307
        /* Check for indirect call. */
3308
        if((u32)regs->u_regs[UREG_G1] == 0)
3309
                base = 1;
3310
 
3311
        filename = getname((char *)AA(regs->u_regs[base + UREG_I0]));
3312
        error = PTR_ERR(filename);
3313
        if(IS_ERR(filename))
3314
                goto out;
3315
        error = do_execve32(filename,
3316
                (u32 *)AA((u32)regs->u_regs[base + UREG_I1]),
3317
                (u32 *)AA((u32)regs->u_regs[base + UREG_I2]), regs);
3318
        putname(filename);
3319
 
3320
        if(!error) {
3321
                fprs_write(0);
3322
                current->thread.xfsr[0] = 0;
3323
                current->thread.fpsaved[0] = 0;
3324
                regs->tstate &= ~TSTATE_PEF;
3325
        }
3326
out:
3327
        return error;
3328
}
3329
 
3330
#ifdef CONFIG_MODULES
3331
 
3332
extern asmlinkage unsigned long sys_create_module(const char *name_user, size_t size);
3333
 
3334
asmlinkage unsigned long sys32_create_module(const char *name_user, __kernel_size_t32 size)
3335
{
3336
        return sys_create_module(name_user, (size_t)size);
3337
}
3338
 
3339
extern asmlinkage int sys_init_module(const char *name_user, struct module *mod_user);
3340
 
3341
/* Hey, when you're trying to init module, take time and prepare us a nice 64bit
3342
 * module structure, even if from 32bit modutils... Why to pollute kernel... :))
3343
 */
3344
asmlinkage int sys32_init_module(const char *name_user, struct module *mod_user)
3345
{
3346
        return sys_init_module(name_user, mod_user);
3347
}
3348
 
3349
extern asmlinkage int sys_delete_module(const char *name_user);
3350
 
3351
asmlinkage int sys32_delete_module(const char *name_user)
3352
{
3353
        return sys_delete_module(name_user);
3354
}
3355
 
3356
struct module_info32 {
3357
        u32 addr;
3358
        u32 size;
3359
        u32 flags;
3360
        s32 usecount;
3361
};
3362
 
3363
/* Query various bits about modules.  */
3364
 
3365
static inline long
3366
get_mod_name(const char *user_name, char **buf)
3367
{
3368
        unsigned long page;
3369
        long retval;
3370
 
3371
        if ((unsigned long)user_name >= TASK_SIZE
3372
            && !segment_eq(get_fs (), KERNEL_DS))
3373
                return -EFAULT;
3374
 
3375
        page = __get_free_page(GFP_KERNEL);
3376
        if (!page)
3377
                return -ENOMEM;
3378
 
3379
        retval = strncpy_from_user((char *)page, user_name, PAGE_SIZE);
3380
        if (retval > 0) {
3381
                if (retval < PAGE_SIZE) {
3382
                        *buf = (char *)page;
3383
                        return retval;
3384
                }
3385
                retval = -ENAMETOOLONG;
3386
        } else if (!retval)
3387
                retval = -EINVAL;
3388
 
3389
        free_page(page);
3390
        return retval;
3391
}
3392
 
3393
static inline void
3394
put_mod_name(char *buf)
3395
{
3396
        free_page((unsigned long)buf);
3397
}
3398
 
3399
static __inline__ struct module *find_module(const char *name)
3400
{
3401
        struct module *mod;
3402
 
3403
        for (mod = module_list; mod ; mod = mod->next) {
3404
                if (mod->flags & MOD_DELETED)
3405
                        continue;
3406
                if (!strcmp(mod->name, name))
3407
                        break;
3408
        }
3409
 
3410
        return mod;
3411
}
3412
 
3413
static int
3414
qm_modules(char *buf, size_t bufsize, __kernel_size_t32 *ret)
3415
{
3416
        struct module *mod;
3417
        size_t nmod, space, len;
3418
 
3419
        nmod = space = 0;
3420
 
3421
        for (mod = module_list; mod->next != NULL; mod = mod->next, ++nmod) {
3422
                len = strlen(mod->name)+1;
3423
                if (len > bufsize)
3424
                        goto calc_space_needed;
3425
                if (copy_to_user(buf, mod->name, len))
3426
                        return -EFAULT;
3427
                buf += len;
3428
                bufsize -= len;
3429
                space += len;
3430
        }
3431
 
3432
        if (put_user(nmod, ret))
3433
                return -EFAULT;
3434
        else
3435
                return 0;
3436
 
3437
calc_space_needed:
3438
        space += len;
3439
        while ((mod = mod->next)->next != NULL)
3440
                space += strlen(mod->name)+1;
3441
 
3442
        if (put_user(space, ret))
3443
                return -EFAULT;
3444
        else
3445
                return -ENOSPC;
3446
}
3447
 
3448
static int
3449
qm_deps(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
3450
{
3451
        size_t i, space, len;
3452
 
3453
        if (mod->next == NULL)
3454
                return -EINVAL;
3455
        if (!MOD_CAN_QUERY(mod))
3456
                return put_user(0, ret);
3457
 
3458
        space = 0;
3459
        for (i = 0; i < mod->ndeps; ++i) {
3460
                const char *dep_name = mod->deps[i].dep->name;
3461
 
3462
                len = strlen(dep_name)+1;
3463
                if (len > bufsize)
3464
                        goto calc_space_needed;
3465
                if (copy_to_user(buf, dep_name, len))
3466
                        return -EFAULT;
3467
                buf += len;
3468
                bufsize -= len;
3469
                space += len;
3470
        }
3471
 
3472
        return put_user(i, ret);
3473
 
3474
calc_space_needed:
3475
        space += len;
3476
        while (++i < mod->ndeps)
3477
                space += strlen(mod->deps[i].dep->name)+1;
3478
 
3479
        if (put_user(space, ret))
3480
                return -EFAULT;
3481
        else
3482
                return -ENOSPC;
3483
}
3484
 
3485
static int
3486
qm_refs(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
3487
{
3488
        size_t nrefs, space, len;
3489
        struct module_ref *ref;
3490
 
3491
        if (mod->next == NULL)
3492
                return -EINVAL;
3493
        if (!MOD_CAN_QUERY(mod))
3494
                if (put_user(0, ret))
3495
                        return -EFAULT;
3496
                else
3497
                        return 0;
3498
 
3499
        space = 0;
3500
        for (nrefs = 0, ref = mod->refs; ref ; ++nrefs, ref = ref->next_ref) {
3501
                const char *ref_name = ref->ref->name;
3502
 
3503
                len = strlen(ref_name)+1;
3504
                if (len > bufsize)
3505
                        goto calc_space_needed;
3506
                if (copy_to_user(buf, ref_name, len))
3507
                        return -EFAULT;
3508
                buf += len;
3509
                bufsize -= len;
3510
                space += len;
3511
        }
3512
 
3513
        if (put_user(nrefs, ret))
3514
                return -EFAULT;
3515
        else
3516
                return 0;
3517
 
3518
calc_space_needed:
3519
        space += len;
3520
        while ((ref = ref->next_ref) != NULL)
3521
                space += strlen(ref->ref->name)+1;
3522
 
3523
        if (put_user(space, ret))
3524
                return -EFAULT;
3525
        else
3526
                return -ENOSPC;
3527
}
3528
 
3529
static inline int
3530
qm_symbols(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
3531
{
3532
        size_t i, space, len;
3533
        struct module_symbol *s;
3534
        char *strings;
3535
        unsigned *vals;
3536
 
3537
        if (!MOD_CAN_QUERY(mod))
3538
                if (put_user(0, ret))
3539
                        return -EFAULT;
3540
                else
3541
                        return 0;
3542
 
3543
        space = mod->nsyms * 2*sizeof(u32);
3544
 
3545
        i = len = 0;
3546
        s = mod->syms;
3547
 
3548
        if (space > bufsize)
3549
                goto calc_space_needed;
3550
 
3551
        if (!access_ok(VERIFY_WRITE, buf, space))
3552
                return -EFAULT;
3553
 
3554
        bufsize -= space;
3555
        vals = (unsigned *)buf;
3556
        strings = buf+space;
3557
 
3558
        for (; i < mod->nsyms ; ++i, ++s, vals += 2) {
3559
                len = strlen(s->name)+1;
3560
                if (len > bufsize)
3561
                        goto calc_space_needed;
3562
 
3563
                if (copy_to_user(strings, s->name, len)
3564
                    || __put_user(s->value, vals+0)
3565
                    || __put_user(space, vals+1))
3566
                        return -EFAULT;
3567
 
3568
                strings += len;
3569
                bufsize -= len;
3570
                space += len;
3571
        }
3572
 
3573
        if (put_user(i, ret))
3574
                return -EFAULT;
3575
        else
3576
                return 0;
3577
 
3578
calc_space_needed:
3579
        for (; i < mod->nsyms; ++i, ++s)
3580
                space += strlen(s->name)+1;
3581
 
3582
        if (put_user(space, ret))
3583
                return -EFAULT;
3584
        else
3585
                return -ENOSPC;
3586
}
3587
 
3588
static inline int
3589
qm_info(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
3590
{
3591
        int error = 0;
3592
 
3593
        if (mod->next == NULL)
3594
                return -EINVAL;
3595
 
3596
        if (sizeof(struct module_info32) <= bufsize) {
3597
                struct module_info32 info;
3598
                info.addr = (unsigned long)mod;
3599
                info.size = mod->size;
3600
                info.flags = mod->flags;
3601
                info.usecount =
3602
                        ((mod_member_present(mod, can_unload)
3603
                          && mod->can_unload)
3604
                         ? -1 : atomic_read(&mod->uc.usecount));
3605
 
3606
                if (copy_to_user(buf, &info, sizeof(struct module_info32)))
3607
                        return -EFAULT;
3608
        } else
3609
                error = -ENOSPC;
3610
 
3611
        if (put_user(sizeof(struct module_info32), ret))
3612
                return -EFAULT;
3613
 
3614
        return error;
3615
}
3616
 
3617
asmlinkage int sys32_query_module(char *name_user, int which, char *buf, __kernel_size_t32 bufsize, u32 ret)
3618
{
3619
        struct module *mod;
3620
        int err;
3621
 
3622
        lock_kernel();
3623
        if (name_user == 0) {
3624
                /* This finds "kernel_module" which is not exported. */
3625
                for(mod = module_list; mod->next != NULL; mod = mod->next)
3626
                        ;
3627
        } else {
3628
                long namelen;
3629
                char *name;
3630
 
3631
                if ((namelen = get_mod_name(name_user, &name)) < 0) {
3632
                        err = namelen;
3633
                        goto out;
3634
                }
3635
                err = -ENOENT;
3636
                if (namelen == 0) {
3637
                        /* This finds "kernel_module" which is not exported. */
3638
                        for(mod = module_list; mod->next != NULL; mod = mod->next)
3639
                                ;
3640
                } else if ((mod = find_module(name)) == NULL) {
3641
                        put_mod_name(name);
3642
                        goto out;
3643
                }
3644
                put_mod_name(name);
3645
        }
3646
 
3647
        switch (which)
3648
        {
3649
        case 0:
3650
                err = 0;
3651
                break;
3652
        case QM_MODULES:
3653
                err = qm_modules(buf, bufsize, (__kernel_size_t32 *)AA(ret));
3654
                break;
3655
        case QM_DEPS:
3656
                err = qm_deps(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
3657
                break;
3658
        case QM_REFS:
3659
                err = qm_refs(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
3660
                break;
3661
        case QM_SYMBOLS:
3662
                err = qm_symbols(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
3663
                break;
3664
        case QM_INFO:
3665
                err = qm_info(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
3666
                break;
3667
        default:
3668
                err = -EINVAL;
3669
                break;
3670
        }
3671
out:
3672
        unlock_kernel();
3673
        return err;
3674
}
3675
 
3676
struct kernel_sym32 {
3677
        u32 value;
3678
        char name[60];
3679
};
3680
 
3681
extern asmlinkage int sys_get_kernel_syms(struct kernel_sym *table);
3682
 
3683
asmlinkage int sys32_get_kernel_syms(struct kernel_sym32 *table)
3684
{
3685
        int len, i;
3686
        struct kernel_sym *tbl;
3687
        mm_segment_t old_fs;
3688
 
3689
        len = sys_get_kernel_syms(NULL);
3690
        if (!table) return len;
3691
        tbl = kmalloc (len * sizeof (struct kernel_sym), GFP_KERNEL);
3692
        if (!tbl) return -ENOMEM;
3693
        old_fs = get_fs();
3694
        set_fs (KERNEL_DS);
3695
        sys_get_kernel_syms(tbl);
3696
        set_fs (old_fs);
3697
        for (i = 0; i < len; i++, table++) {
3698
                if (put_user (tbl[i].value, &table->value) ||
3699
                    copy_to_user (table->name, tbl[i].name, 60))
3700
                        break;
3701
        }
3702
        kfree (tbl);
3703
        return i;
3704
}
3705
 
3706
#else /* CONFIG_MODULES */
3707
 
3708
asmlinkage unsigned long
3709
sys32_create_module(const char *name_user, size_t size)
3710
{
3711
        return -ENOSYS;
3712
}
3713
 
3714
asmlinkage int
3715
sys32_init_module(const char *name_user, struct module *mod_user)
3716
{
3717
        return -ENOSYS;
3718
}
3719
 
3720
asmlinkage int
3721
sys32_delete_module(const char *name_user)
3722
{
3723
        return -ENOSYS;
3724
}
3725
 
3726
asmlinkage int
3727
sys32_query_module(const char *name_user, int which, char *buf, size_t bufsize,
3728
                 size_t *ret)
3729
{
3730
        /* Let the program know about the new interface.  Not that
3731
           it'll do them much good.  */
3732
        if (which == 0)
3733
                return 0;
3734
 
3735
        return -ENOSYS;
3736
}
3737
 
3738
asmlinkage int
3739
sys32_get_kernel_syms(struct kernel_sym *table)
3740
{
3741
        return -ENOSYS;
3742
}
3743
 
3744
#endif  /* CONFIG_MODULES */
3745
 
3746
#if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)
3747
/* Stuff for NFS server syscalls... */
3748
struct nfsctl_svc32 {
3749
        u16                     svc32_port;
3750
        s32                     svc32_nthreads;
3751
};
3752
 
3753
struct nfsctl_client32 {
3754
        s8                      cl32_ident[NFSCLNT_IDMAX+1];
3755
        s32                     cl32_naddr;
3756
        struct in_addr          cl32_addrlist[NFSCLNT_ADDRMAX];
3757
        s32                     cl32_fhkeytype;
3758
        s32                     cl32_fhkeylen;
3759
        u8                      cl32_fhkey[NFSCLNT_KEYMAX];
3760
};
3761
 
3762
struct nfsctl_export32 {
3763
        s8                      ex32_client[NFSCLNT_IDMAX+1];
3764
        s8                      ex32_path[NFS_MAXPATHLEN+1];
3765
        __kernel_dev_t32        ex32_dev;
3766
        __kernel_ino_t32        ex32_ino;
3767
        s32                     ex32_flags;
3768
        __kernel_uid_t32        ex32_anon_uid;
3769
        __kernel_gid_t32        ex32_anon_gid;
3770
};
3771
 
3772
struct nfsctl_uidmap32 {
3773
        u32                     ug32_ident;   /* char * */
3774
        __kernel_uid_t32        ug32_uidbase;
3775
        s32                     ug32_uidlen;
3776
        u32                     ug32_udimap;  /* uid_t * */
3777
        __kernel_uid_t32        ug32_gidbase;
3778
        s32                     ug32_gidlen;
3779
        u32                     ug32_gdimap;  /* gid_t * */
3780
};
3781
 
3782
struct nfsctl_fhparm32 {
3783
        struct sockaddr         gf32_addr;
3784
        __kernel_dev_t32        gf32_dev;
3785
        __kernel_ino_t32        gf32_ino;
3786
        s32                     gf32_version;
3787
};
3788
 
3789
struct nfsctl_fdparm32 {
3790
        struct sockaddr         gd32_addr;
3791
        s8                      gd32_path[NFS_MAXPATHLEN+1];
3792
        s32                     gd32_version;
3793
};
3794
 
3795
struct nfsctl_fsparm32 {
3796
        struct sockaddr         gd32_addr;
3797
        s8                      gd32_path[NFS_MAXPATHLEN+1];
3798
        s32                     gd32_maxlen;
3799
};
3800
 
3801
struct nfsctl_arg32 {
3802
        s32                     ca32_version;   /* safeguard */
3803
        union {
3804
                struct nfsctl_svc32     u32_svc;
3805
                struct nfsctl_client32  u32_client;
3806
                struct nfsctl_export32  u32_export;
3807
                struct nfsctl_uidmap32  u32_umap;
3808
                struct nfsctl_fhparm32  u32_getfh;
3809
                struct nfsctl_fdparm32  u32_getfd;
3810
                struct nfsctl_fsparm32  u32_getfs;
3811
        } u;
3812
#define ca32_svc        u.u32_svc
3813
#define ca32_client     u.u32_client
3814
#define ca32_export     u.u32_export
3815
#define ca32_umap       u.u32_umap
3816
#define ca32_getfh      u.u32_getfh
3817
#define ca32_getfd      u.u32_getfd
3818
#define ca32_getfs      u.u32_getfs
3819
#define ca32_authd      u.u32_authd
3820
};
3821
 
3822
union nfsctl_res32 {
3823
        __u8                    cr32_getfh[NFS_FHSIZE];
3824
        struct knfsd_fh         cr32_getfs;
3825
};
3826
 
3827
static int nfs_svc32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3828
{
3829
        int err;
3830
 
3831
        err = __get_user(karg->ca_version, &arg32->ca32_version);
3832
        err |= __get_user(karg->ca_svc.svc_port, &arg32->ca32_svc.svc32_port);
3833
        err |= __get_user(karg->ca_svc.svc_nthreads, &arg32->ca32_svc.svc32_nthreads);
3834
        return err;
3835
}
3836
 
3837
static int nfs_clnt32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3838
{
3839
        int err;
3840
 
3841
        err = __get_user(karg->ca_version, &arg32->ca32_version);
3842
        err |= copy_from_user(&karg->ca_client.cl_ident[0],
3843
                          &arg32->ca32_client.cl32_ident[0],
3844
                          NFSCLNT_IDMAX);
3845
        err |= __get_user(karg->ca_client.cl_naddr, &arg32->ca32_client.cl32_naddr);
3846
        err |= copy_from_user(&karg->ca_client.cl_addrlist[0],
3847
                          &arg32->ca32_client.cl32_addrlist[0],
3848
                          (sizeof(struct in_addr) * NFSCLNT_ADDRMAX));
3849
        err |= __get_user(karg->ca_client.cl_fhkeytype,
3850
                      &arg32->ca32_client.cl32_fhkeytype);
3851
        err |= __get_user(karg->ca_client.cl_fhkeylen,
3852
                      &arg32->ca32_client.cl32_fhkeylen);
3853
        err |= copy_from_user(&karg->ca_client.cl_fhkey[0],
3854
                          &arg32->ca32_client.cl32_fhkey[0],
3855
                          NFSCLNT_KEYMAX);
3856
        return (err ? -EFAULT : 0);
3857
}
3858
 
3859
static int nfs_exp32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3860
{
3861
        int err;
3862
 
3863
        err = __get_user(karg->ca_version, &arg32->ca32_version);
3864
        err |= copy_from_user(&karg->ca_export.ex_client[0],
3865
                          &arg32->ca32_export.ex32_client[0],
3866
                          NFSCLNT_IDMAX);
3867
        err |= copy_from_user(&karg->ca_export.ex_path[0],
3868
                          &arg32->ca32_export.ex32_path[0],
3869
                          NFS_MAXPATHLEN);
3870
        err |= __get_user(karg->ca_export.ex_dev,
3871
                      &arg32->ca32_export.ex32_dev);
3872
        err |= __get_user(karg->ca_export.ex_ino,
3873
                      &arg32->ca32_export.ex32_ino);
3874
        err |= __get_user(karg->ca_export.ex_flags,
3875
                      &arg32->ca32_export.ex32_flags);
3876
        err |= __get_user(karg->ca_export.ex_anon_uid,
3877
                      &arg32->ca32_export.ex32_anon_uid);
3878
        err |= __get_user(karg->ca_export.ex_anon_gid,
3879
                      &arg32->ca32_export.ex32_anon_gid);
3880
        karg->ca_export.ex_anon_uid = high2lowuid(karg->ca_export.ex_anon_uid);
3881
        karg->ca_export.ex_anon_gid = high2lowgid(karg->ca_export.ex_anon_gid);
3882
        return (err ? -EFAULT : 0);
3883
}
3884
 
3885
static int nfs_uud32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3886
{
3887
        u32 uaddr;
3888
        int i;
3889
        int err;
3890
 
3891
        memset(karg, 0, sizeof(*karg));
3892
        if(__get_user(karg->ca_version, &arg32->ca32_version))
3893
                return -EFAULT;
3894
        karg->ca_umap.ug_ident = (char *)get_free_page(GFP_USER);
3895
        if(!karg->ca_umap.ug_ident)
3896
                return -ENOMEM;
3897
        err = __get_user(uaddr, &arg32->ca32_umap.ug32_ident);
3898
        if(strncpy_from_user(karg->ca_umap.ug_ident,
3899
                             (char *)A(uaddr), PAGE_SIZE) <= 0)
3900
                return -EFAULT;
3901
        err |= __get_user(karg->ca_umap.ug_uidbase,
3902
                      &arg32->ca32_umap.ug32_uidbase);
3903
        err |= __get_user(karg->ca_umap.ug_uidlen,
3904
                      &arg32->ca32_umap.ug32_uidlen);
3905
        err |= __get_user(uaddr, &arg32->ca32_umap.ug32_udimap);
3906
        if (err)
3907
                return -EFAULT;
3908
        karg->ca_umap.ug_udimap = kmalloc((sizeof(uid_t) * karg->ca_umap.ug_uidlen),
3909
                                          GFP_USER);
3910
        if(!karg->ca_umap.ug_udimap)
3911
                return -ENOMEM;
3912
        for(i = 0; i < karg->ca_umap.ug_uidlen; i++)
3913
                err |= __get_user(karg->ca_umap.ug_udimap[i],
3914
                              &(((__kernel_uid_t32 *)A(uaddr))[i]));
3915
        err |= __get_user(karg->ca_umap.ug_gidbase,
3916
                      &arg32->ca32_umap.ug32_gidbase);
3917
        err |= __get_user(karg->ca_umap.ug_uidlen,
3918
                      &arg32->ca32_umap.ug32_gidlen);
3919
        err |= __get_user(uaddr, &arg32->ca32_umap.ug32_gdimap);
3920
        if (err)
3921
                return -EFAULT;
3922
        karg->ca_umap.ug_gdimap = kmalloc((sizeof(gid_t) * karg->ca_umap.ug_uidlen),
3923
                                          GFP_USER);
3924
        if(!karg->ca_umap.ug_gdimap)
3925
                return -ENOMEM;
3926
        for(i = 0; i < karg->ca_umap.ug_gidlen; i++)
3927
                err |= __get_user(karg->ca_umap.ug_gdimap[i],
3928
                              &(((__kernel_gid_t32 *)A(uaddr))[i]));
3929
 
3930
        return (err ? -EFAULT : 0);
3931
}
3932
 
3933
static int nfs_getfh32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3934
{
3935
        int err;
3936
 
3937
        err = __get_user(karg->ca_version, &arg32->ca32_version);
3938
        err |= copy_from_user(&karg->ca_getfh.gf_addr,
3939
                          &arg32->ca32_getfh.gf32_addr,
3940
                          (sizeof(struct sockaddr)));
3941
        err |= __get_user(karg->ca_getfh.gf_dev,
3942
                      &arg32->ca32_getfh.gf32_dev);
3943
        err |= __get_user(karg->ca_getfh.gf_ino,
3944
                      &arg32->ca32_getfh.gf32_ino);
3945
        err |= __get_user(karg->ca_getfh.gf_version,
3946
                      &arg32->ca32_getfh.gf32_version);
3947
        return (err ? -EFAULT : 0);
3948
}
3949
 
3950
static int nfs_getfd32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3951
{
3952
        int err;
3953
 
3954
        err = __get_user(karg->ca_version, &arg32->ca32_version);
3955
        err |= copy_from_user(&karg->ca_getfd.gd_addr,
3956
                          &arg32->ca32_getfd.gd32_addr,
3957
                          (sizeof(struct sockaddr)));
3958
        err |= copy_from_user(&karg->ca_getfd.gd_path,
3959
                          &arg32->ca32_getfd.gd32_path,
3960
                          (NFS_MAXPATHLEN+1));
3961
        err |= __get_user(karg->ca_getfd.gd_version,
3962
                      &arg32->ca32_getfd.gd32_version);
3963
        return (err ? -EFAULT : 0);
3964
}
3965
 
3966
static int nfs_getfs32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3967
{
3968
        int err;
3969
 
3970
        err = __get_user(karg->ca_version, &arg32->ca32_version);
3971
        err |= copy_from_user(&karg->ca_getfs.gd_addr,
3972
                          &arg32->ca32_getfs.gd32_addr,
3973
                          (sizeof(struct sockaddr)));
3974
        err |= copy_from_user(&karg->ca_getfs.gd_path,
3975
                          &arg32->ca32_getfs.gd32_path,
3976
                          (NFS_MAXPATHLEN+1));
3977
        err |= __get_user(karg->ca_getfs.gd_maxlen,
3978
                      &arg32->ca32_getfs.gd32_maxlen);
3979
        return (err ? -EFAULT : 0);
3980
}
3981
 
3982
/* This really doesn't need translations, we are only passing
3983
 * back a union which contains opaque nfs file handle data.
3984
 */
3985
static int nfs_getfh32_res_trans(union nfsctl_res *kres, union nfsctl_res32 *res32)
3986
{
3987
        return (copy_to_user(res32, kres, sizeof(*res32)) ? -EFAULT : 0);
3988
}
3989
 
3990
int asmlinkage sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsctl_res32 *res32)
3991
{
3992
        struct nfsctl_arg *karg = NULL;
3993
        union nfsctl_res *kres = NULL;
3994
        mm_segment_t oldfs;
3995
        int err;
3996
 
3997
        karg = kmalloc(sizeof(*karg), GFP_USER);
3998
        if(!karg)
3999
                return -ENOMEM;
4000
        if(res32) {
4001
                kres = kmalloc(sizeof(*kres), GFP_USER);
4002
                if(!kres) {
4003
                        kfree(karg);
4004
                        return -ENOMEM;
4005
                }
4006
        }
4007
        switch(cmd) {
4008
        case NFSCTL_SVC:
4009
                err = nfs_svc32_trans(karg, arg32);
4010
                break;
4011
        case NFSCTL_ADDCLIENT:
4012
                err = nfs_clnt32_trans(karg, arg32);
4013
                break;
4014
        case NFSCTL_DELCLIENT:
4015
                err = nfs_clnt32_trans(karg, arg32);
4016
                break;
4017
        case NFSCTL_EXPORT:
4018
        case NFSCTL_UNEXPORT:
4019
                err = nfs_exp32_trans(karg, arg32);
4020
                break;
4021
        /* This one is unimplemented, be we're ready for it. */
4022
        case NFSCTL_UGIDUPDATE:
4023
                err = nfs_uud32_trans(karg, arg32);
4024
                break;
4025
        case NFSCTL_GETFH:
4026
                err = nfs_getfh32_trans(karg, arg32);
4027
                break;
4028
        case NFSCTL_GETFD:
4029
                err = nfs_getfd32_trans(karg, arg32);
4030
                break;
4031
        case NFSCTL_GETFS:
4032
                err = nfs_getfs32_trans(karg, arg32);
4033
                break;
4034
        default:
4035
                err = -EINVAL;
4036
                break;
4037
        }
4038
        if(err)
4039
                goto done;
4040
        oldfs = get_fs();
4041
        set_fs(KERNEL_DS);
4042
        err = sys_nfsservctl(cmd, karg, kres);
4043
        set_fs(oldfs);
4044
 
4045
        if (err)
4046
                goto done;
4047
 
4048
        if((cmd == NFSCTL_GETFH) ||
4049
           (cmd == NFSCTL_GETFD) ||
4050
           (cmd == NFSCTL_GETFS))
4051
                err = nfs_getfh32_res_trans(kres, res32);
4052
 
4053
done:
4054
        if(karg) {
4055
                if(cmd == NFSCTL_UGIDUPDATE) {
4056
                        if(karg->ca_umap.ug_ident)
4057
                                kfree(karg->ca_umap.ug_ident);
4058
                        if(karg->ca_umap.ug_udimap)
4059
                                kfree(karg->ca_umap.ug_udimap);
4060
                        if(karg->ca_umap.ug_gdimap)
4061
                                kfree(karg->ca_umap.ug_gdimap);
4062
                }
4063
                kfree(karg);
4064
        }
4065
        if(kres)
4066
                kfree(kres);
4067
        return err;
4068
}
4069
#else /* !NFSD */
4070
extern asmlinkage long sys_ni_syscall(void);
4071
int asmlinkage sys32_nfsservctl(int cmd, void *notused, void *notused2)
4072
{
4073
        return sys_ni_syscall();
4074
}
4075
#endif
4076
 
4077
/* Translations due to time_t size differences.  Which affects all
4078
   sorts of things, like timeval and itimerval.  */
4079
 
4080
extern struct timezone sys_tz;
4081
extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz);
4082
 
4083
asmlinkage int sys32_gettimeofday(struct timeval32 *tv, struct timezone *tz)
4084
{
4085
        if (tv) {
4086
                struct timeval ktv;
4087
                do_gettimeofday(&ktv);
4088
                if (put_tv32(tv, &ktv))
4089
                        return -EFAULT;
4090
        }
4091
        if (tz) {
4092
                if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
4093
                        return -EFAULT;
4094
        }
4095
        return 0;
4096
}
4097
 
4098
asmlinkage int sys32_settimeofday(struct timeval32 *tv, struct timezone *tz)
4099
{
4100
        struct timeval ktv;
4101
        struct timezone ktz;
4102
 
4103
        if (tv) {
4104
                if (get_tv32(&ktv, tv))
4105
                        return -EFAULT;
4106
        }
4107
        if (tz) {
4108
                if (copy_from_user(&ktz, tz, sizeof(ktz)))
4109
                        return -EFAULT;
4110
        }
4111
 
4112
        return do_sys_settimeofday(tv ? &ktv : NULL, tz ? &ktz : NULL);
4113
}
4114
 
4115
extern int do_getitimer(int which, struct itimerval *value);
4116
 
4117
asmlinkage int sys32_getitimer(int which, struct itimerval32 *it)
4118
{
4119
        struct itimerval kit;
4120
        int error;
4121
 
4122
        error = do_getitimer(which, &kit);
4123
        if (!error && put_it32(it, &kit))
4124
                error = -EFAULT;
4125
 
4126
        return error;
4127
}
4128
 
4129
extern int do_setitimer(int which, struct itimerval *, struct itimerval *);
4130
 
4131
asmlinkage int sys32_setitimer(int which, struct itimerval32 *in, struct itimerval32 *out)
4132
{
4133
        struct itimerval kin, kout;
4134
        int error;
4135
 
4136
        if (in) {
4137
                if (get_it32(&kin, in))
4138
                        return -EFAULT;
4139
        } else
4140
                memset(&kin, 0, sizeof(kin));
4141
 
4142
        error = do_setitimer(which, &kin, out ? &kout : NULL);
4143
        if (error || !out)
4144
                return error;
4145
        if (put_it32(out, &kout))
4146
                return -EFAULT;
4147
 
4148
        return 0;
4149
 
4150
}
4151
 
4152
asmlinkage int sys_utimes(char *, struct timeval *);
4153
 
4154
asmlinkage int sys32_utimes(char *filename, struct timeval32 *tvs)
4155
{
4156
        char *kfilename;
4157
        struct timeval ktvs[2];
4158
        mm_segment_t old_fs;
4159
        int ret;
4160
 
4161
        kfilename = getname(filename);
4162
        ret = PTR_ERR(kfilename);
4163
        if (!IS_ERR(kfilename)) {
4164
                if (tvs) {
4165
                        if (get_tv32(&ktvs[0], tvs) ||
4166
                            get_tv32(&ktvs[1], 1+tvs))
4167
                                return -EFAULT;
4168
                }
4169
 
4170
                old_fs = get_fs();
4171
                set_fs(KERNEL_DS);
4172
                ret = sys_utimes(kfilename, &ktvs[0]);
4173
                set_fs(old_fs);
4174
 
4175
                putname(kfilename);
4176
        }
4177
        return ret;
4178
}
4179
 
4180
/* These are here just in case some old sparc32 binary calls it. */
4181
asmlinkage int sys32_pause(void)
4182
{
4183
        current->state = TASK_INTERRUPTIBLE;
4184
        schedule();
4185
        return -ERESTARTNOHAND;
4186
}
4187
 
4188
/* PCI config space poking. */
4189
extern asmlinkage int sys_pciconfig_read(unsigned long bus,
4190
                                         unsigned long dfn,
4191
                                         unsigned long off,
4192
                                         unsigned long len,
4193
                                         unsigned char *buf);
4194
 
4195
extern asmlinkage int sys_pciconfig_write(unsigned long bus,
4196
                                          unsigned long dfn,
4197
                                          unsigned long off,
4198
                                          unsigned long len,
4199
                                          unsigned char *buf);
4200
 
4201
asmlinkage int sys32_pciconfig_read(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
4202
{
4203
        return sys_pciconfig_read((unsigned long) bus,
4204
                                  (unsigned long) dfn,
4205
                                  (unsigned long) off,
4206
                                  (unsigned long) len,
4207
                                  (unsigned char *)AA(ubuf));
4208
}
4209
 
4210
asmlinkage int sys32_pciconfig_write(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
4211
{
4212
        return sys_pciconfig_write((unsigned long) bus,
4213
                                   (unsigned long) dfn,
4214
                                   (unsigned long) off,
4215
                                   (unsigned long) len,
4216
                                   (unsigned char *)AA(ubuf));
4217
}
4218
 
4219
extern asmlinkage int sys_prctl(int option, unsigned long arg2, unsigned long arg3,
4220
                                unsigned long arg4, unsigned long arg5);
4221
 
4222
asmlinkage int sys32_prctl(int option, u32 arg2, u32 arg3, u32 arg4, u32 arg5)
4223
{
4224
        return sys_prctl(option,
4225
                         (unsigned long) arg2,
4226
                         (unsigned long) arg3,
4227
                         (unsigned long) arg4,
4228
                         (unsigned long) arg5);
4229
}
4230
 
4231
 
4232
extern asmlinkage ssize_t sys_pread(unsigned int fd, char * buf,
4233
                                    size_t count, loff_t pos);
4234
 
4235
extern asmlinkage ssize_t sys_pwrite(unsigned int fd, const char * buf,
4236
                                     size_t count, loff_t pos);
4237
 
4238
typedef __kernel_ssize_t32 ssize_t32;
4239
 
4240
asmlinkage ssize_t32 sys32_pread(unsigned int fd, char *ubuf,
4241
                                 __kernel_size_t32 count, u32 poshi, u32 poslo)
4242
{
4243
        return sys_pread(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
4244
}
4245
 
4246
asmlinkage ssize_t32 sys32_pwrite(unsigned int fd, char *ubuf,
4247
                                  __kernel_size_t32 count, u32 poshi, u32 poslo)
4248
{
4249
        return sys_pwrite(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
4250
}
4251
 
4252
extern asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count);
4253
 
4254
asmlinkage ssize_t32 sys32_readahead(int fd, u32 offhi, u32 offlo, s32 count)
4255
{
4256
        return sys_readahead(fd, ((loff_t)AA(offhi) << 32) | AA(offlo), count);
4257
}
4258
 
4259
extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
4260
 
4261
asmlinkage int sys32_sendfile(int out_fd, int in_fd, __kernel_off_t32 *offset, s32 count)
4262
{
4263
        mm_segment_t old_fs = get_fs();
4264
        int ret;
4265
        off_t of;
4266
 
4267
        if (offset && get_user(of, offset))
4268
                return -EFAULT;
4269
 
4270
        set_fs(KERNEL_DS);
4271
        ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
4272
        set_fs(old_fs);
4273
 
4274
        if (offset && put_user(of, offset))
4275
                return -EFAULT;
4276
 
4277
        return ret;
4278
}
4279
 
4280
/* Handle adjtimex compatability. */
4281
 
4282
struct timex32 {
4283
        u32 modes;
4284
        s32 offset, freq, maxerror, esterror;
4285
        s32 status, constant, precision, tolerance;
4286
        struct timeval32 time;
4287
        s32 tick;
4288
        s32 ppsfreq, jitter, shift, stabil;
4289
        s32 jitcnt, calcnt, errcnt, stbcnt;
4290
        s32  :32; s32  :32; s32  :32; s32  :32;
4291
        s32  :32; s32  :32; s32  :32; s32  :32;
4292
        s32  :32; s32  :32; s32  :32; s32  :32;
4293
};
4294
 
4295
extern int do_adjtimex(struct timex *);
4296
 
4297
asmlinkage int sys32_adjtimex(struct timex32 *utp)
4298
{
4299
        struct timex txc;
4300
        int ret;
4301
 
4302
        memset(&txc, 0, sizeof(struct timex));
4303
 
4304
        if(get_user(txc.modes, &utp->modes) ||
4305
           __get_user(txc.offset, &utp->offset) ||
4306
           __get_user(txc.freq, &utp->freq) ||
4307
           __get_user(txc.maxerror, &utp->maxerror) ||
4308
           __get_user(txc.esterror, &utp->esterror) ||
4309
           __get_user(txc.status, &utp->status) ||
4310
           __get_user(txc.constant, &utp->constant) ||
4311
           __get_user(txc.precision, &utp->precision) ||
4312
           __get_user(txc.tolerance, &utp->tolerance) ||
4313
           __get_user(txc.time.tv_sec, &utp->time.tv_sec) ||
4314
           __get_user(txc.time.tv_usec, &utp->time.tv_usec) ||
4315
           __get_user(txc.tick, &utp->tick) ||
4316
           __get_user(txc.ppsfreq, &utp->ppsfreq) ||
4317
           __get_user(txc.jitter, &utp->jitter) ||
4318
           __get_user(txc.shift, &utp->shift) ||
4319
           __get_user(txc.stabil, &utp->stabil) ||
4320
           __get_user(txc.jitcnt, &utp->jitcnt) ||
4321
           __get_user(txc.calcnt, &utp->calcnt) ||
4322
           __get_user(txc.errcnt, &utp->errcnt) ||
4323
           __get_user(txc.stbcnt, &utp->stbcnt))
4324
                return -EFAULT;
4325
 
4326
        ret = do_adjtimex(&txc);
4327
 
4328
        if(put_user(txc.modes, &utp->modes) ||
4329
           __put_user(txc.offset, &utp->offset) ||
4330
           __put_user(txc.freq, &utp->freq) ||
4331
           __put_user(txc.maxerror, &utp->maxerror) ||
4332
           __put_user(txc.esterror, &utp->esterror) ||
4333
           __put_user(txc.status, &utp->status) ||
4334
           __put_user(txc.constant, &utp->constant) ||
4335
           __put_user(txc.precision, &utp->precision) ||
4336
           __put_user(txc.tolerance, &utp->tolerance) ||
4337
           __put_user(txc.time.tv_sec, &utp->time.tv_sec) ||
4338
           __put_user(txc.time.tv_usec, &utp->time.tv_usec) ||
4339
           __put_user(txc.tick, &utp->tick) ||
4340
           __put_user(txc.ppsfreq, &utp->ppsfreq) ||
4341
           __put_user(txc.jitter, &utp->jitter) ||
4342
           __put_user(txc.shift, &utp->shift) ||
4343
           __put_user(txc.stabil, &utp->stabil) ||
4344
           __put_user(txc.jitcnt, &utp->jitcnt) ||
4345
           __put_user(txc.calcnt, &utp->calcnt) ||
4346
           __put_user(txc.errcnt, &utp->errcnt) ||
4347
           __put_user(txc.stbcnt, &utp->stbcnt))
4348
                ret = -EFAULT;
4349
 
4350
        return ret;
4351
}
4352
 
4353
/* This is just a version for 32-bit applications which does
4354
 * not force O_LARGEFILE on.
4355
 */
4356
 
4357
asmlinkage long sparc32_open(const char * filename, int flags, int mode)
4358
{
4359
        char * tmp;
4360
        int fd, error;
4361
 
4362
        tmp = getname(filename);
4363
        fd = PTR_ERR(tmp);
4364
        if (!IS_ERR(tmp)) {
4365
                fd = get_unused_fd();
4366
                if (fd >= 0) {
4367
                        struct file * f = filp_open(tmp, flags, mode);
4368
                        error = PTR_ERR(f);
4369
                        if (IS_ERR(f))
4370
                                goto out_error;
4371
                        fd_install(fd, f);
4372
                }
4373
out:
4374
                putname(tmp);
4375
        }
4376
        return fd;
4377
 
4378
out_error:
4379
        put_unused_fd(fd);
4380
        fd = error;
4381
        goto out;
4382
}
4383
 
4384
extern unsigned long do_mremap(unsigned long addr,
4385
        unsigned long old_len, unsigned long new_len,
4386
        unsigned long flags, unsigned long new_addr);
4387
 
4388
asmlinkage unsigned long sys32_mremap(unsigned long addr,
4389
        unsigned long old_len, unsigned long new_len,
4390
        unsigned long flags, u32 __new_addr)
4391
{
4392
        struct vm_area_struct *vma;
4393
        unsigned long ret = -EINVAL;
4394
        unsigned long new_addr = AA(__new_addr);
4395
 
4396
        if (old_len > 0xf0000000UL || new_len > 0xf0000000UL)
4397
                goto out;
4398
        if (addr > 0xf0000000UL - old_len)
4399
                goto out;
4400
        down_write(&current->mm->mmap_sem);
4401
        if (flags & MREMAP_FIXED) {
4402
                if (new_addr > 0xf0000000UL - new_len)
4403
                        goto out_sem;
4404
        } else if (addr > 0xf0000000UL - new_len) {
4405
                unsigned long map_flags = 0;
4406
                struct file *file = NULL;
4407
 
4408
                ret = -ENOMEM;
4409
                if (!(flags & MREMAP_MAYMOVE))
4410
                        goto out_sem;
4411
 
4412
                vma = find_vma(current->mm, addr);
4413
                if (vma) {
4414
                        if (vma->vm_flags & VM_SHARED)
4415
                                map_flags |= MAP_SHARED;
4416
                        file = vma->vm_file;
4417
                }
4418
 
4419
                /* MREMAP_FIXED checked above. */
4420
                new_addr = get_unmapped_area(file, addr, new_len,
4421
                                    vma ? vma->vm_pgoff : 0,
4422
                                    map_flags);
4423
                ret = new_addr;
4424
                if (new_addr & ~PAGE_MASK)
4425
                        goto out_sem;
4426
                flags |= MREMAP_FIXED;
4427
        }
4428
        ret = do_mremap(addr, old_len, new_len, flags, new_addr);
4429
out_sem:
4430
        up_write(&current->mm->mmap_sem);
4431
out:
4432
        return ret;
4433
}
4434
 
4435
extern asmlinkage long sys_setpriority(int which, int who, int niceval);
4436
 
4437
asmlinkage int sys_setpriority32(u32 which, u32 who, u32 niceval)
4438
{
4439
        return sys_setpriority((int) which,
4440
                               (int) who,
4441
                               (int) niceval);
4442
}
4443
 
4444
struct __sysctl_args32 {
4445
        u32 name;
4446
        int nlen;
4447
        u32 oldval;
4448
        u32 oldlenp;
4449
        u32 newval;
4450
        u32 newlen;
4451
        u32 __unused[4];
4452
};
4453
 
4454
extern asmlinkage long sys32_sysctl(struct __sysctl_args32 *args)
4455
{
4456
#ifndef CONFIG_SYSCTL
4457
        return -ENOSYS;
4458
#else
4459
        struct __sysctl_args32 tmp;
4460
        int error;
4461
        size_t oldlen, *oldlenp = NULL;
4462
        unsigned long addr = (((long)&args->__unused[0]) + 7) & ~7;
4463
 
4464
        if (copy_from_user(&tmp, args, sizeof(tmp)))
4465
                return -EFAULT;
4466
 
4467
        if (tmp.oldval && tmp.oldlenp) {
4468
                /* Duh, this is ugly and might not work if sysctl_args
4469
                   is in read-only memory, but do_sysctl does indirectly
4470
                   a lot of uaccess in both directions and we'd have to
4471
                   basically copy the whole sysctl.c here, and
4472
                   glibc's __sysctl uses rw memory for the structure
4473
                   anyway.  */
4474
                if (get_user(oldlen, (u32 *)A(tmp.oldlenp)) ||
4475
                    put_user(oldlen, (size_t *)addr))
4476
                        return -EFAULT;
4477
                oldlenp = (size_t *)addr;
4478
        }
4479
 
4480
        lock_kernel();
4481
        error = do_sysctl((int *)A(tmp.name), tmp.nlen, (void *)A(tmp.oldval),
4482
                          oldlenp, (void *)A(tmp.newval), tmp.newlen);
4483
        unlock_kernel();
4484
        if (oldlenp) {
4485
                if (!error) {
4486
                        if (get_user(oldlen, (size_t *)addr) ||
4487
                            put_user(oldlen, (u32 *)A(tmp.oldlenp)))
4488
                                error = -EFAULT;
4489
                }
4490
                copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused));
4491
        }
4492
        return error;
4493
#endif
4494
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.