x86, smap: Reduce the SMAP overhead for signal handling
[deliverable/linux.git] / arch / x86 / ia32 / ia32_signal.c
CommitLineData
1da177e4
LT
1/*
2 * linux/arch/x86_64/ia32/ia32_signal.c
3 *
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 *
6 * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson
7 * 2000-06-20 Pentium III FXSR, SSE support by Gareth Hughes
8 * 2000-12-* x86-64 compatibility mode signal handling by Andi Kleen
1da177e4
LT
9 */
10
11#include <linux/sched.h>
12#include <linux/mm.h>
13#include <linux/smp.h>
1da177e4 14#include <linux/kernel.h>
1da177e4
LT
15#include <linux/errno.h>
16#include <linux/wait.h>
1da177e4
LT
17#include <linux/unistd.h>
18#include <linux/stddef.h>
19#include <linux/personality.h>
20#include <linux/compat.h>
9fbbd4dd 21#include <linux/binfmts.h>
1da177e4
LT
22#include <asm/ucontext.h>
23#include <asm/uaccess.h>
24#include <asm/i387.h>
1361b83a 25#include <asm/fpu-internal.h>
1da177e4
LT
26#include <asm/ptrace.h>
27#include <asm/ia32_unistd.h>
28#include <asm/user32.h>
29#include <asm/sigcontext32.h>
1da177e4 30#include <asm/proto.h>
af65d648 31#include <asm/vdso.h>
d98f9d84 32#include <asm/sigframe.h>
f28f0c23 33#include <asm/sighandling.h>
2f06de06 34#include <asm/sys_ia32.h>
d98f9d84 35
f28f0c23 36#define FIX_EFLAGS __FIX_EFLAGS
1da177e4
LT
37
38int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
39{
3b4b7570 40 int err = 0;
0b91f45b 41 bool ia32 = test_thread_flag(TIF_IA32);
99b9cdf7
TG
42
43 if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
1da177e4
LT
44 return -EFAULT;
45
3b4b7570
HS
46 put_user_try {
47 /* If you change siginfo_t structure, please make sure that
48 this code is fixed accordingly.
49 It should never copy any pad contained in the structure
50 to avoid security leaks, but must copy the generic
51 3 ints plus the relevant union member. */
52 put_user_ex(from->si_signo, &to->si_signo);
53 put_user_ex(from->si_errno, &to->si_errno);
54 put_user_ex((short)from->si_code, &to->si_code);
55
56 if (from->si_code < 0) {
57 put_user_ex(from->si_pid, &to->si_pid);
58 put_user_ex(from->si_uid, &to->si_uid);
59 put_user_ex(ptr_to_compat(from->si_ptr), &to->si_ptr);
60 } else {
61 /*
62 * First 32bits of unions are always present:
63 * si_pid === si_band === si_tid === si_addr(LS half)
64 */
65 put_user_ex(from->_sifields._pad[0],
66 &to->_sifields._pad[0]);
67 switch (from->si_code >> 16) {
68 case __SI_FAULT >> 16:
69 break;
a0727e8c
WD
70 case __SI_SYS >> 16:
71 put_user_ex(from->si_syscall, &to->si_syscall);
72 put_user_ex(from->si_arch, &to->si_arch);
73 break;
3b4b7570 74 case __SI_CHLD >> 16:
e7084fd5
PA
75 if (ia32) {
76 put_user_ex(from->si_utime, &to->si_utime);
77 put_user_ex(from->si_stime, &to->si_stime);
78 } else {
79 put_user_ex(from->si_utime, &to->_sifields._sigchld_x32._utime);
80 put_user_ex(from->si_stime, &to->_sifields._sigchld_x32._stime);
81 }
3b4b7570
HS
82 put_user_ex(from->si_status, &to->si_status);
83 /* FALL THROUGH */
84 default:
85 case __SI_KILL >> 16:
86 put_user_ex(from->si_uid, &to->si_uid);
87 break;
88 case __SI_POLL >> 16:
89 put_user_ex(from->si_fd, &to->si_fd);
90 break;
91 case __SI_TIMER >> 16:
92 put_user_ex(from->si_overrun, &to->si_overrun);
93 put_user_ex(ptr_to_compat(from->si_ptr),
94 &to->si_ptr);
95 break;
96 /* This is not generated by the kernel as of now. */
97 case __SI_RT >> 16:
98 case __SI_MESGQ >> 16:
99 put_user_ex(from->si_uid, &to->si_uid);
100 put_user_ex(from->si_int, &to->si_int);
101 break;
102 }
1da177e4 103 }
3b4b7570
HS
104 } put_user_catch(err);
105
1da177e4
LT
106 return err;
107}
108
109int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
110{
3b4b7570 111 int err = 0;
1da177e4 112 u32 ptr32;
99b9cdf7
TG
113
114 if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t)))
1da177e4
LT
115 return -EFAULT;
116
3b4b7570
HS
117 get_user_try {
118 get_user_ex(to->si_signo, &from->si_signo);
119 get_user_ex(to->si_errno, &from->si_errno);
120 get_user_ex(to->si_code, &from->si_code);
1da177e4 121
3b4b7570
HS
122 get_user_ex(to->si_pid, &from->si_pid);
123 get_user_ex(to->si_uid, &from->si_uid);
124 get_user_ex(ptr32, &from->si_ptr);
125 to->si_ptr = compat_ptr(ptr32);
126 } get_user_catch(err);
1da177e4
LT
127
128 return err;
129}
130
99b9cdf7 131asmlinkage long sys32_sigsuspend(int history0, int history1, old_sigset_t mask)
1da177e4 132{
905f29e2 133 sigset_t blocked;
905f29e2 134 siginitset(&blocked, mask);
68f3f16d 135 return sigsuspend(&blocked);
1da177e4
LT
136}
137
99b9cdf7
TG
138asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
139 stack_ia32_t __user *uoss_ptr,
140 struct pt_regs *regs)
1da177e4 141{
99b9cdf7 142 stack_t uss, uoss;
3b4b7570 143 int ret, err = 0;
99b9cdf7
TG
144 mm_segment_t seg;
145
146 if (uss_ptr) {
1da177e4 147 u32 ptr;
99b9cdf7
TG
148
149 memset(&uss, 0, sizeof(stack_t));
3b4b7570
HS
150 if (!access_ok(VERIFY_READ, uss_ptr, sizeof(stack_ia32_t)))
151 return -EFAULT;
152
153 get_user_try {
154 get_user_ex(ptr, &uss_ptr->ss_sp);
155 get_user_ex(uss.ss_flags, &uss_ptr->ss_flags);
156 get_user_ex(uss.ss_size, &uss_ptr->ss_size);
157 } get_user_catch(err);
158
159 if (err)
1da177e4
LT
160 return -EFAULT;
161 uss.ss_sp = compat_ptr(ptr);
162 }
99b9cdf7
TG
163 seg = get_fs();
164 set_fs(KERNEL_DS);
65ea5b03 165 ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs->sp);
99b9cdf7 166 set_fs(seg);
1da177e4 167 if (ret >= 0 && uoss_ptr) {
3b4b7570
HS
168 if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_ia32_t)))
169 return -EFAULT;
170
171 put_user_try {
172 put_user_ex(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp);
173 put_user_ex(uoss.ss_flags, &uoss_ptr->ss_flags);
174 put_user_ex(uoss.ss_size, &uoss_ptr->ss_size);
175 } put_user_catch(err);
176
177 if (err)
1da177e4 178 ret = -EFAULT;
99b9cdf7
TG
179 }
180 return ret;
1da177e4
LT
181}
182
183/*
184 * Do a signal return; undo the signal stack.
185 */
a967bb3f
HS
186#define loadsegment_gs(v) load_gs_index(v)
187#define loadsegment_fs(v) loadsegment(fs, v)
188#define loadsegment_ds(v) loadsegment(ds, v)
189#define loadsegment_es(v) loadsegment(es, v)
190
191#define get_user_seg(seg) ({ unsigned int v; savesegment(seg, v); v; })
192#define set_user_seg(seg, v) loadsegment_##seg(v)
193
b78a5b52 194#define COPY(x) { \
3b4b7570 195 get_user_ex(regs->x, &sc->x); \
1da177e4 196}
1da177e4 197
8801ead4
HS
198#define GET_SEG(seg) ({ \
199 unsigned short tmp; \
200 get_user_ex(tmp, &sc->seg); \
201 tmp; \
202})
203
204#define COPY_SEG_CPL3(seg) do { \
205 regs->seg = GET_SEG(seg) | 3; \
206} while (0)
1da177e4 207
8c6e5ce0 208#define RELOAD_SEG(seg) { \
a967bb3f
HS
209 unsigned int pre = GET_SEG(seg); \
210 unsigned int cur = get_user_seg(seg); \
8c6e5ce0
HS
211 pre |= 3; \
212 if (pre != cur) \
a967bb3f 213 set_user_seg(seg, pre); \
8c6e5ce0 214}
99b9cdf7
TG
215
216static int ia32_restore_sigcontext(struct pt_regs *regs,
217 struct sigcontext_ia32 __user *sc,
047ce935 218 unsigned int *pax)
99b9cdf7 219{
a967bb3f 220 unsigned int tmpflags, err = 0;
ab513701 221 void __user *buf;
99b9cdf7
TG
222 u32 tmp;
223
224 /* Always make any pending restarted system calls return -EINTR */
225 current_thread_info()->restart_block.fn = do_no_restart_syscall;
226
3b4b7570
HS
227 get_user_try {
228 /*
229 * Reload fs and gs if they have changed in the signal
230 * handler. This does not handle long fs/gs base changes in
231 * the handler, but does not clobber them at least in the
232 * normal case.
233 */
a967bb3f 234 RELOAD_SEG(gs);
3b4b7570
HS
235 RELOAD_SEG(fs);
236 RELOAD_SEG(ds);
237 RELOAD_SEG(es);
238
239 COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
240 COPY(dx); COPY(cx); COPY(ip);
241 /* Don't touch extended registers */
242
243 COPY_SEG_CPL3(cs);
244 COPY_SEG_CPL3(ss);
245
246 get_user_ex(tmpflags, &sc->flags);
247 regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
248 /* disable syscall checks */
249 regs->orig_ax = -1;
250
251 get_user_ex(tmp, &sc->fpstate);
252 buf = compat_ptr(tmp);
3b4b7570
HS
253
254 get_user_ex(*pax, &sc->ax);
255 } get_user_catch(err);
256
5e88353d
PA
257 err |= restore_i387_xstate_ia32(buf);
258
1da177e4 259 return err;
1da177e4
LT
260}
261
262asmlinkage long sys32_sigreturn(struct pt_regs *regs)
263{
3b0d29ee 264 struct sigframe_ia32 __user *frame = (struct sigframe_ia32 __user *)(regs->sp-8);
1da177e4 265 sigset_t set;
65ea5b03 266 unsigned int ax;
1da177e4
LT
267
268 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
269 goto badframe;
270 if (__get_user(set.sig[0], &frame->sc.oldmask)
271 || (_COMPAT_NSIG_WORDS > 1
99b9cdf7
TG
272 && __copy_from_user((((char *) &set.sig) + 4),
273 &frame->extramask,
1da177e4
LT
274 sizeof(frame->extramask))))
275 goto badframe;
276
905f29e2 277 set_current_blocked(&set);
99b9cdf7 278
65ea5b03 279 if (ia32_restore_sigcontext(regs, &frame->sc, &ax))
1da177e4 280 goto badframe;
65ea5b03 281 return ax;
1da177e4
LT
282
283badframe:
284 signal_fault(regs, frame, "32bit sigreturn");
285 return 0;
99b9cdf7 286}
1da177e4
LT
287
288asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
289{
3b0d29ee 290 struct rt_sigframe_ia32 __user *frame;
1da177e4 291 sigset_t set;
65ea5b03 292 unsigned int ax;
1da177e4
LT
293 struct pt_regs tregs;
294
3b0d29ee 295 frame = (struct rt_sigframe_ia32 __user *)(regs->sp - 4);
1da177e4
LT
296
297 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
298 goto badframe;
299 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
300 goto badframe;
301
905f29e2 302 set_current_blocked(&set);
99b9cdf7 303
65ea5b03 304 if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
1da177e4
LT
305 goto badframe;
306
307 tregs = *regs;
308 if (sys32_sigaltstack(&frame->uc.uc_stack, NULL, &tregs) == -EFAULT)
309 goto badframe;
310
65ea5b03 311 return ax;
1da177e4
LT
312
313badframe:
99b9cdf7 314 signal_fault(regs, frame, "32bit rt sigreturn");
1da177e4 315 return 0;
99b9cdf7 316}
1da177e4
LT
317
318/*
319 * Set up a signal frame.
320 */
321
99b9cdf7 322static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc,
ab513701 323 void __user *fpstate,
99b9cdf7 324 struct pt_regs *regs, unsigned int mask)
1da177e4 325{
a967bb3f 326 int err = 0;
1da177e4 327
3b4b7570 328 put_user_try {
a967bb3f
HS
329 put_user_ex(get_user_seg(gs), (unsigned int __user *)&sc->gs);
330 put_user_ex(get_user_seg(fs), (unsigned int __user *)&sc->fs);
331 put_user_ex(get_user_seg(ds), (unsigned int __user *)&sc->ds);
332 put_user_ex(get_user_seg(es), (unsigned int __user *)&sc->es);
3b4b7570
HS
333
334 put_user_ex(regs->di, &sc->di);
335 put_user_ex(regs->si, &sc->si);
336 put_user_ex(regs->bp, &sc->bp);
337 put_user_ex(regs->sp, &sc->sp);
338 put_user_ex(regs->bx, &sc->bx);
339 put_user_ex(regs->dx, &sc->dx);
340 put_user_ex(regs->cx, &sc->cx);
341 put_user_ex(regs->ax, &sc->ax);
51e7dc70 342 put_user_ex(current->thread.trap_nr, &sc->trapno);
3b4b7570
HS
343 put_user_ex(current->thread.error_code, &sc->err);
344 put_user_ex(regs->ip, &sc->ip);
345 put_user_ex(regs->cs, (unsigned int __user *)&sc->cs);
346 put_user_ex(regs->flags, &sc->flags);
347 put_user_ex(regs->sp, &sc->sp_at_signal);
348 put_user_ex(regs->ss, (unsigned int __user *)&sc->ss);
349
350 put_user_ex(ptr_to_compat(fpstate), &sc->fpstate);
351
352 /* non-iBCS2 extensions.. */
353 put_user_ex(mask, &sc->oldmask);
354 put_user_ex(current->thread.cr2, &sc->cr2);
355 } put_user_catch(err);
1da177e4
LT
356
357 return err;
358}
359
360/*
361 * Determine which stack to use..
362 */
99b9cdf7 363static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
3c1c7f10 364 size_t frame_size,
ab513701 365 void **fpstate)
1da177e4 366{
65ea5b03 367 unsigned long sp;
1da177e4
LT
368
369 /* Default to using normal stack */
65ea5b03 370 sp = regs->sp;
1da177e4
LT
371
372 /* This is the X/Open sanctioned signal stack switching. */
373 if (ka->sa.sa_flags & SA_ONSTACK) {
65ea5b03
PA
374 if (sas_ss_flags(sp) == 0)
375 sp = current->sas_ss_sp + current->sas_ss_size;
1da177e4
LT
376 }
377
378 /* This is the legacy signal stack switching. */
8bee3f0a 379 else if ((regs->ss & 0xffff) != __USER32_DS &&
1da177e4 380 !(ka->sa.sa_flags & SA_RESTORER) &&
99b9cdf7 381 ka->sa.sa_restorer)
65ea5b03 382 sp = (unsigned long) ka->sa.sa_restorer;
1da177e4 383
3c1c7f10
SS
384 if (used_math()) {
385 sp = sp - sig_xstate_ia32_size;
386 *fpstate = (struct _fpstate_ia32 *) sp;
99ea1b93
HS
387 if (save_i387_xstate_ia32(*fpstate) < 0)
388 return (void __user *) -1L;
3c1c7f10
SS
389 }
390
65ea5b03 391 sp -= frame_size;
d347f372
MO
392 /* Align the stack pointer according to the i386 ABI,
393 * i.e. so that on function entry ((sp + 4) & 15) == 0. */
65ea5b03
PA
394 sp = ((sp + 4) & -16ul) - 4;
395 return (void __user *) sp;
1da177e4
LT
396}
397
0928d6ef 398int ia32_setup_frame(int sig, struct k_sigaction *ka,
99b9cdf7 399 compat_sigset_t *set, struct pt_regs *regs)
1da177e4 400{
3b0d29ee 401 struct sigframe_ia32 __user *frame;
99b9cdf7 402 void __user *restorer;
1da177e4 403 int err = 0;
ab513701 404 void __user *fpstate = NULL;
1da177e4 405
99b9cdf7
TG
406 /* copy_to_user optimizes that into a single 8 byte store */
407 static const struct {
408 u16 poplmovl;
409 u32 val;
410 u16 int80;
99b9cdf7
TG
411 } __attribute__((packed)) code = {
412 0xb858, /* popl %eax ; movl $...,%eax */
413 __NR_ia32_sigreturn,
414 0x80cd, /* int $0x80 */
99b9cdf7
TG
415 };
416
3c1c7f10 417 frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate);
1da177e4
LT
418
419 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
3d0aedd9 420 return -EFAULT;
1da177e4 421
2ba48e16 422 if (__put_user(sig, &frame->sig))
3d0aedd9 423 return -EFAULT;
1da177e4 424
2ba48e16 425 if (ia32_setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0]))
3d0aedd9 426 return -EFAULT;
1da177e4
LT
427
428 if (_COMPAT_NSIG_WORDS > 1) {
2ba48e16
HS
429 if (__copy_to_user(frame->extramask, &set->sig[1],
430 sizeof(frame->extramask)))
3d0aedd9 431 return -EFAULT;
1da177e4 432 }
1da177e4 433
af65d648 434 if (ka->sa.sa_flags & SA_RESTORER) {
99b9cdf7 435 restorer = ka->sa.sa_restorer;
af65d648
RM
436 } else {
437 /* Return stub is in 32bit vsyscall page */
1a3e4ca4 438 if (current->mm->context.vdso)
af65d648
RM
439 restorer = VDSO32_SYMBOL(current->mm->context.vdso,
440 sigreturn);
441 else
ade1af77 442 restorer = &frame->retcode;
af65d648 443 }
99b9cdf7 444
3b4b7570
HS
445 put_user_try {
446 put_user_ex(ptr_to_compat(restorer), &frame->pretcode);
447
448 /*
449 * These are actually not used anymore, but left because some
450 * gdb versions depend on them as a marker.
451 */
452 put_user_ex(*((u64 *)&code), (u64 *)frame->retcode);
453 } put_user_catch(err);
454
1da177e4 455 if (err)
3d0aedd9 456 return -EFAULT;
1da177e4
LT
457
458 /* Set up registers for signal handler */
65ea5b03
PA
459 regs->sp = (unsigned long) frame;
460 regs->ip = (unsigned long) ka->sa.sa_handler;
1da177e4 461
536e3ee4 462 /* Make -mregparm=3 work */
65ea5b03
PA
463 regs->ax = sig;
464 regs->dx = 0;
465 regs->cx = 0;
536e3ee4 466
b6edbb1e
JF
467 loadsegment(ds, __USER32_DS);
468 loadsegment(es, __USER32_DS);
1da177e4 469
99b9cdf7
TG
470 regs->cs = __USER32_CS;
471 regs->ss = __USER32_DS;
1da177e4 472
1d001df1 473 return 0;
1da177e4
LT
474}
475
0928d6ef 476int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
99b9cdf7 477 compat_sigset_t *set, struct pt_regs *regs)
1da177e4 478{
3b0d29ee 479 struct rt_sigframe_ia32 __user *frame;
af65d648 480 void __user *restorer;
1da177e4 481 int err = 0;
ab513701 482 void __user *fpstate = NULL;
1da177e4 483
99b9cdf7
TG
484 /* __copy_to_user optimizes that into a single 8 byte store */
485 static const struct {
486 u8 movl;
487 u32 val;
488 u16 int80;
9cc3c49e 489 u8 pad;
99b9cdf7
TG
490 } __attribute__((packed)) code = {
491 0xb8,
492 __NR_ia32_rt_sigreturn,
493 0x80cd,
494 0,
495 };
496
3c1c7f10 497 frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate);
1da177e4
LT
498
499 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
3d0aedd9 500 return -EFAULT;
1da177e4 501
3b4b7570
HS
502 put_user_try {
503 put_user_ex(sig, &frame->sig);
504 put_user_ex(ptr_to_compat(&frame->info), &frame->pinfo);
505 put_user_ex(ptr_to_compat(&frame->uc), &frame->puc);
1da177e4 506
3b4b7570
HS
507 /* Create the ucontext. */
508 if (cpu_has_xsave)
509 put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
510 else
511 put_user_ex(0, &frame->uc.uc_flags);
512 put_user_ex(0, &frame->uc.uc_link);
513 put_user_ex(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
514 put_user_ex(sas_ss_flags(regs->sp),
515 &frame->uc.uc_stack.ss_flags);
516 put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
3b4b7570
HS
517
518 if (ka->sa.sa_flags & SA_RESTORER)
519 restorer = ka->sa.sa_restorer;
520 else
521 restorer = VDSO32_SYMBOL(current->mm->context.vdso,
522 rt_sigreturn);
523 put_user_ex(ptr_to_compat(restorer), &frame->pretcode);
524
525 /*
526 * Not actually used anymore, but left because some gdb
527 * versions need it.
528 */
529 put_user_ex(*((u64 *)&code), (u64 *)frame->retcode);
530 } put_user_catch(err);
1da177e4 531
5e88353d
PA
532 err |= copy_siginfo_to_user32(&frame->info, info);
533 err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
534 regs, set->sig[0]);
535 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
536
1da177e4 537 if (err)
3d0aedd9 538 return -EFAULT;
1da177e4
LT
539
540 /* Set up registers for signal handler */
65ea5b03
PA
541 regs->sp = (unsigned long) frame;
542 regs->ip = (unsigned long) ka->sa.sa_handler;
1da177e4 543
a7aacdf9 544 /* Make -mregparm=3 work */
65ea5b03
PA
545 regs->ax = sig;
546 regs->dx = (unsigned long) &frame->info;
547 regs->cx = (unsigned long) &frame->uc;
a7aacdf9 548
b6edbb1e
JF
549 loadsegment(ds, __USER32_DS);
550 loadsegment(es, __USER32_DS);
99b9cdf7
TG
551
552 regs->cs = __USER32_CS;
553 regs->ss = __USER32_DS;
1da177e4 554
1d001df1 555 return 0;
1da177e4 556}
This page took 0.726792 seconds and 5 git commands to generate.