ࡱ; W  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~Root Entry  !"#$%&'()+-./023456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmno ®`VTextStarWriter 5.0{:-  SfxDocumentInfo Mike R|1+Mike |1tMike |1 Info 0 Info 1 Info 2 Info 3 R|1+VB<44Standard LIBIMBEDDED LIBIMBEDDED TASK,0,1,H32,0,100,1,2368;328127;110;0;322492;14971;330797;0;0SW5HDR.0|1t!Outline0 #ZOSWG, A<  #$%&'()*./0123456789:;<=>?@ABCDGHK  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFQRSTU0R'&@ TimesNewRomanX'@d X' @X'(!@. !. XA'2*@'dxdxdxdXXJJ@NX@dPM' TimesNewRoman$' '(. . p. @ . . . . . P. . . !. $. `'. 0*. -. /. 2. p5. @8. ;. =. @. 6')(02 StandardStandard@ Text bodyStandard Text body2A'List Text bodyList'CaptionStandardCaption'' '2A'JJIndexStandardIndex'JJ FooterStandardFooter@('JJ<|?SBX sb Z Standard StarBASICSBX ARSBX AR SBX AR2c%bqqOh+'0 h t 27@TK.@ϟ@La@֫5Mike Mike SW5HDR.0|1t! Frameformat ZeichenformatTextformatvorlageStandard Text bodyListCaption IndexFooterRoot 10Standard  Illustration Table TextDrawingY  .Y  .Y  .Y .q= GeneralGeneraldNC#,###.00#,###.00SystemNC #,##0.00 CCC#,##0.00 CCCNC$#,##0.--;[RED]-$#,##0.-- $#,##0.---$#,##0.--REDNC$ MM/DD/YYYYMM/DD/YYYY def/SystemNC%MM/DD/YYMM/DD/YY def/SystemNC&NNNNMMMM DD, YYYYNNNNMMMM  DD, YYYYSystemNC' MMM D, YYMMM D, YY def/SystemNC. [HH]:MM:SS.00 [HH ]:MM:SS .00NC3MM/DD/YYYY HH:MM:SS MM/DD/YYYY HH :MM:SS  NCK MMM D, YYYYMMM D, YYYY def/SystemNCL MMMM D, YYYYMMMM  D, YYYY def/SystemNCM NN, MMM D, YYNN, MMM D, YY def/SystemNCNNN, MMMM D, YYYYNN, MMMM  D, YYYY def/SystemNCONNNNMMMM D, YYYYNNNNMMMM  D, YYYY def/SystemNCP D. MMM. YYYYD. MMM. YYYYDIN 5008 (EN 28601)NCQ D. MMMM YYYYD. MMMM  YYYYDIN 5008 (EN 28601)NCRMM-DDMM-DDDIN 5008 (EN 28601)NCSYY-MM-DDYY-MM-DDDIN 5008 (EN 28601)NCT YYYY-MM-DDYYYY-MM-DDDIN 5008 (EN 28601)NCUWWWWNCBXoeP<p5 2$99 SAP/=APdddAPddA PAu Prk FooterSYAPddADPN;T2SA @A0SAAP/=APdddAPddZSW5HDR.0|1tC(569a(Build:5169)(SV569)]D!Address Book Fileaddress! Frameformat ZeichenformatTextformatvorlageStandard Text bodyListCaption IndexFooterRoot 10Standard  Illustration Table TextDrawingd B1 4 5*jK standard.dic soffice.dicZsun.dic@ IgnoreAllListY  .Y  .Y  .Y .6N T3Signal HandlingSA A @T$SA A @T9Objectives of signalsSA A @T$SA A @To3Notify process that a particular event has occurredS1APdddA A @T<S1APdddA A @TMCause process to S1APdddA A @T<S1APdddA A @TUexecute signal handler orS1APdddA A @TUsuffer the default actionS1APdddA A @T<S1APdddA A @Tq5Default actions are signal type dependent and includeS1APdddA A @T<S1APdddA A @TRabort destroy processS1APdddA A @Tb&dump destroy process and create dumpS1APdddA A @TUignore ignore the signalS1APdddA A @Tk/continue if TASK_STOPPED change to TASK_RUNNINGS1APdddA A @T[stop set state to TASK_STOPPEDS1APdddA A @T<S1APdddA A @TYLinux defines 31 signal types and mgmt structures are in Linux/include/asm-i386/signal.hS'APdddA @A89A8:YT<S1APdddA A @Tf31 #define SIGHUP 1SHAPdddACourierA A @Tf32 #define SIGINT 2SHAPdddACourierA A @Tg33 #define SIGQUIT 3SHAPdddACourierA A @Tf34 #define SIGILL 4SHAPdddACourierA A @Tg35 #define SIGTRAP 5SHAPdddACourierA A @Tg36 #define SIGABRT 6SHAPdddACourierA A @Tf37 #define SIGIOT 6SHAPdddACourierA A @Tf38 #define SIGBUS 7SHAPdddACourierA A @Tf39 #define SIGFPE 8SHAPdddACourierA A @Tg40 #define SIGKILL 9SHAPdddACourierA A @Th41 #define SIGUSR1 10SHAPdddACourierA A @Th42 #define SIGSEGV 11SHAPdddACourierA A @TX :SHAPdddACourierA A @TY : SHAPdddACourierA A @T<S1APdddA A @T[System calls related to signalsS1APdddA A @T<S1APdddA A @TRkill send a signalS1APdddA A @Te)sigaction/signal define a signal handlerS1APdddA A @T`$sigpending test for pending signalsS1APdddA A @Ta%sigprocmask specify blocked signals S1APdddA A @TZsigsuspend wait for a signalS1APdddA A @T<S1APdddA A @T<S1APdddA A @T<S1APdddA A @T}7Signal operations can be viewed as two phase proceduresS;APdddA PA A @T<S1APdddA A @TI Signal send -S1APdddA A @T<S1APdddA A @Tb&Can be done only by a running process S1APdddA A @TNFlips a bit in the task struct of the recipient to indicate signal now pendingS1APdddA A @T<S1APdddA A @TLSignal receive -S1APdddA A @T2S'APdddA @T_The next time the recipient process is about to leave kernel mode the required action is taken.S1APdddA A @T<S1APdddA A @Ti-Recall the code for exiting from system callsS1APdddA A @T<S1APdddA A @T` ALIGNSHAPdddACourierA A @Tasignal_return:SHAPdddACourierA A @T; sti # we can get here from an interrupt handlerSHAPdddACourierA A @Tx% testl $(VM_MASK),EFLAGS(%esp)SHAPdddACourierA A @Ti movl %esp,%eaxSHAPdddACourierA A @Tp jne v86_signal_returnSHAPdddACourierA A @Ti xorl %edx,%edxSHAPdddACourierA A @Tv# call SYMBOL_NAME(do_signal)SHAPdddACourierA A @Tj jmp restore_allSHAPdddACourierA A @TSSHAPdddACourierA A @TGFurther complicationsS'APdddA @T2S'APdddA @Tj8Processes can block (some) signals from being delivered.S'APdddA @Tf4These must remain pending until the block is removedS'APpdddpA @T2S'APdddA @TyGSignal delivery is masked while corresponding signal is being processedS'APdddA @T2S'APdddA @T4Signals are ignored if all of the following are trueS'APdddA @A8 A8 4T<S1APdddA  A @Tq5Target process is not being traced by another processS1APpdddpA  A @Tx.The signal is not blocked by the target prcessS1APpdddpA  A @A8 T~The signal is being ignored by the target process either via explicit command to do so or because ignore is the default actionSBAPodddm A  A @A@. A8  T2S'APdddA @T2S'APdddA @Tj$Actions taken on receipt of a signalS;APdddA PA A @T<S1APdddA A @TTExplicitly ignore itS'APdddA @A8T<S1APdddA A @TVExecute the default actionS1APdddA A @T<S1APdddA A @TQAbort (HUP, INT)S1APdddA A @Ta!Dump (implies abort) (BUS, SEGV)S'APdddA @A8TNIgnore (WINCH)S1APdddA A @TKStop (STOP)S1APdddA A @TNContinue (CONT)S1APdddA A @T<S1APdddA A @Tl0Catch and execute a user supplied signal handlerS1APdddA A @T<S1APdddA A @TYSending a signal to a processS1APdddA A @T<S1APdddA A @TTThe kill system call can be used to send any signal to any process group or process.S1APdddA A @T<S1APdddA A @Ti#include SHAPdddACourierA A @Tf#include SHAPdddACourierA A @TSSHAPdddACourierA A @Tpint kill(pid_t pid, int sig);SHAPdddACourierA A @T<S1APdddA A @Tq5If pid is positive, then signal sig is sent to pid. S1APdddA A @T<S1APdddA A @T`If pid equals 0, then sig is sent to every process in the process group of the current process.S1APdddA A @T<S1APdddA A @TIf pid equals -1, then sig is sent to every process except for the first one, from higher numbers in the process table to lower. S'APdddA @A8HA8IT<S1APdddA A @TVIf pid is less than -1, then sig is sent to every process in the process group -pid.S1APdddA A @T<S1APdddA A @TNIf sig is 0, then no signal is sent, but error checking is still performed.S1APdddA A @T<S1APdddA A @TH RETURN VALUES1APdddA A @T<S1APdddA A @T[On success, zero is returned. On error, -1 is returned, and errno is set appropriately.S1APdddA A @T<S1APdddA A @TFS;APdddA PA A @Ti-Specifying signal handlers and signal actionsS1APdddA A @T2S'APdddA @Tp4The signal() system call has been traditionally usedS1APdddA A @T<S1APdddA A @Tg #include SHAPdddACourierA A @T: void (*signal(int signum, void (*sighandler)(int)))(int);SHAPdddACourierA A @TSSHAPdddACourierA A @Tw;The more general sigaction() system call is now recommendedS1APdddA A @T<S1APdddA A @Tg #include SHAPdddACourierA A @T7 int sigaction(int signum, const struct sigaction *act,SHAPdddACourierA A @Tq struct sigaction *oldact);SHAPdddACourierA A @TT SHAPdddACourierA A @TKBoth specify the action taken by a process on receipt of a specific signal.S1APdddA A @T2S'APdddA @TUsignum specifies the signal and can be any valid signal except SIGKILL and SIGSTOPS8APdd:dSA @A@. A8HA8 A8IUTMSBAPdd:dSA A @A@. T^sighandler specifies a user written function that is called by the kernel when signal receivedSLAPdd:dSA  A A @A@. A8  ^TWSLAPdd:dSA  A A @A@. TOIf act is non-null, the new action for signal signum is installed from act. SLAPdd:dSA  A A @A@. A8 TMSBAPdd:dSA A @A@. T>If oldact is non-null, the previous action is saved in oldact.SBAPdd:dSA A @A@. A8  TMSBAPdd:dSA A @A@. TFS;APdddA PA A @TDMan page for sigaction specifies the following structure definition S1APdddA A @A8  T2S'APdddA @Ti struct sigaction SHAPdddACourierA A @TU {SHAPdddACourierA A @Tu" void (*sa_handler)(int);SHAPdddACourierA A @T9 void (*sa_sigaction)(int, siginfo_t *, void *);SHAPdddACourierA A @Tm sigset_t sa_mask;SHAPdddACourierA A @Tj int sa_flags;SHAPdddACourierA A @Tw$ void (*sa_restorer)(void);SHAPdddACourierA A @TY }SHAPdddACourierA A @T2S'APdddA @TSThis structure appears to be at variance with what the kernel routine expects so...S1APdddA A @T<S1APdddA A @TPman is incorrectS'APdddA @A8TXor libc wrapper fixes it up.S1APdddA A @T<S1APdddA A @Td(The parameters are described as follows:S1APdddA A @T<S1APdddA A @T=The sa_restorer element is obsolete and should not be used. S1APdddA A @A8 T<S1APdddA A @Tsa_handler specifies the action to be associated with signum and may be SIG_DFL for the default action, SIG_IGN to ignore this signal, or a pointer to a signal handling function.S1APdddA A @A8  T<S1APdddA A @T"sa_mask gives a mask of signals which should be blocked during execution of the signal handler. In addition, the signal which triggered the handler will be blocked, unless the SA_NODEFER or SA_NOMASK flags are used.S1APdddA A @A8 T2S'APdddA @Tsa_flags specifies a set of flags which modify the behaviour of the signal handling process. It is formed by the bitwise OR of zero or more of the following:S1APdddA A @A8 T<S1APdddA A @T<S1APdddA A @T[Flag bit definitions:S;APdddA PA A @T<S1APdddA A @TH SA_NOCLDSTOPS1APdddA A @T If signum is SIGCHLD, do not receive notification when child processes stop (i.e., when child processes receive one of SIGSTOP, SIGTSTP, SIGTTIN or SIGTTOU).S'APdddA @A8wA8xT<S1APdddA A @TZSA_ONESHOT or SA_RESETHANDS'APdddA @A8Tx Restore the signal action to the default state once the signal handler has been called. (This is the default.)S1APdddA A @T<S1APdddA A @TZ SA_RESTART S'APdddA @A8 A8 Tr Provide behaviour compatible with BSD signal semantics by making certain system calls restartable across signals.S1APdddA A @T<S1APdddA A @TZSA_NOMASK or SA_NODEFER S'APdddA @A8TQDo not prevent the signal from being received from within its own signal handler.S1APdddA A @T<S1APdddA A @T\SA_SIGINFO S'APdddA @A8 A8 TThe signal handler takes 3 arguments, not one. In this case, sa_sigaction should be set instead of sa_handler. (The sa_sigaction field was added in Linux 2.1.86.)S1APdddA A @T<S1APdddA A @T`The siginfo_t parameter to sa_sigaction signal handler is a struct with the following elementsS1APdddA A @T<S1APdddA A @Tm siginfo_t {S'APdddA @A8A8CourierT2 int si_signo; /* Signal number */SHAPdddACourierA A @T3 int si_errno; /* An errno value */SHAPdddACourierA A @T0 int si_code; /* Signal code */SHAPdddACourierA A @T7 pid_t si_pid; /* Sending process ID */SHAPdddACourierA A @T= uid_t si_uid; /* Real UID sending process */SHAPdddACourierA A @T9 int si_status; /* Exit value or signal */SHAPdddACourierA A @T7 clock_t si_utime; /* User time consumed */SHAPdddACourierA A @T9 clock_t si_stime; /* System time consumed */SHAPdddACourierA A @T1 sigval_t si_value; /* Signal value */SHAPdddACourierA A @T4 int si_int; /* POSIX.1b signal */SHAPdddACourierA A @T4 void * si_ptr; /* POSIX.1b signal */SHAPdddACourierA A @T8 void * si_addr; /* Memory loc of fault */SHAPdddACourierA A @T/ int si_band; /* Band event */SHAPdddACourierA A @T4 int si_fd; /* File descriptor */SHAPdddACourierA A @T[ }SHAPdddACourierA A @TSSHAPdddACourierA A @TOSDAPdddA TimesNewRomanA @T@si_signo, si_errno and si_code are defined for all signals. SNAPdddA PA TimesNewRomanA @A8@A8 A8  A8 !TDkill(2), POSIX.1b signals and SIGCHLD fill in si_pid and si_uid. SDAPdddA TimesNewRomanA @A8DA8 .4A8 9?T:SIGCHLD also fills in si_status, si_utime and si_stime. SDAPdddA TimesNewRomanA @A8:A8  A8 "*A8 /7TGsi_int and si_ptr are specified by the sender of the POSIX.1b signal. SDAPdddA TimesNewRomanA @A8GA8 A8  T{SIGILL, SIGFPE, SIGSEGV and SIGBUS fill in si_addr with the address of the fault. SIGPOLL fills in si_band and si_fd. SDAPdddA TimesNewRomanA @A8{A8 -4A8 fnA8fkA8 qwTOsi_code indicates why this signal was sent. It is a value, not a bitmask. SNAPdddA TimesNewRomanA A @A8 TYSNAPdddA TimesNewRomanA A @TGThe values which are possible for any signal are listed in this table:SNAPdddA TimesNewRomanA A @TSSHAPdddACourierA A @TSSHAPdddACourierA A @Ty&+------------------------------------+SHAPdddACourierA A @Ty&| si_code |SHAPdddACourierA A @Ty&+-----------+------------------------+SHAPdddACourierA A @Ty&|Value | Signal origin |SHAPdddACourierA A @Ty&+-----------+------------------------+SHAPdddACourierA A @Ty&|SI_USER | kill, sigsend or raise |SHAPdddACourierA A @Ty&+-----------+------------------------+SHAPdddACourierA A @Ty&|SI_KERNEL | The kernel |SHAPdddACourierA A @Ty&+-----------+------------------------+SHAPdddACourierA A @Ty&|SI_QUEUE | sigqueue |SHAPdddACourierA A @Ty&+-----------+------------------------+SHAPdddACourierA A @Ty&|SI_TIMER | timer expired |SHAPdddACourierA A @Ty&+-----------+------------------------+SHAPdddACourierA A @Ty&|SI_MESGQ | mesq state changed |SHAPdddACourierA A @Ty&+-----------+------------------------+SHAPdddACourierA A @Ty&|SI_ASYNCIO | AIO completed |SHAPdddACourierA A @Ty&+-----------+------------------------+SHAPdddACourierA A @T<S1APdddA A @TNetc... etc.. etc..S1APdddA A @TlKernel data structuresSKAPdddA PAA A @TSSHAPdddACourierA A @T*A maximum of 64 signals may now be definedSNAPdddA TimesNewRomanA A @T>Bit maps representing signals thus fit in 2 long words on i386SNAPdddA TimesNewRomanA A @TYSNAPdddA TimesNewRomanA A @TV12 SHAPdddACourierA A @Tf13 #define _NSIG 64SHAPdddACourierA A @Tj14 #define _NSIG_BPW 32SHAPdddACourierA A @T}*15 #define _NSIG_WORDS (_NSIG / _NSIG_BPW)SHAPdddACourierA A @TV16 SHAPdddACourierA A @TSSHAPdddACourierA A @Tf19 typedef struct {SHAPdddACourierA A @Tv#20 unsigned long sig[_NSIG_WORDS];SHAPdddACourierA A @Ta21 } sigset_t;SHAPdddACourierA A @TSSHAPdddACourierA A @TGEach process has an dynamically allocated but possibly shared table... SNAPdddA TimesNewRomanA A @TJThe count element is the number of processes currently sharing this table SNAPdddA TimesNewRomanA A @TSSHAPdddACourierA A @Tm247 struct signal_struct {SHAPdddACourierA A @Tg248 atomic_t count;SHAPdddACourierA A @Ty&249 struct k_sigaction action[_NSIG];SHAPdddACourierA A @Tk250 spinlock_t siglock;SHAPdddACourierA A @TY251 };SHAPdddACourierA A @TW252 SHAPdddACourierA A @TSSHAPdddACourierA A @TVThis is a wrapper can be used to add kernel only private data to the "real deal" belowSNAPdddA TimesNewRomanA A @TYSNAPdddA TimesNewRomanA A @Tk150 struct k_sigaction {SHAPdddACourierA A @Tl151 struct sigaction sa;SHAPdddACourierA A @TY152 };SHAPdddACourierA A @TSSHAPdddACourierA A @TWThe sigaction structure... S1APdddA A @T<S1APdddA A @TW142 SHAPdddACourierA A @Ti143 struct sigaction {SHAPdddACourierA A @Tr144 __sighandler_t sa_handler;SHAPdddACourierA A @To145 unsigned long sa_flags;SHAPdddACourierA A @Tr146 void (*sa_restorer)(void);SHAPdddACourierA A @T;147 sigset_t sa_mask; /* mask last for extensibility */SHAPdddACourierA A @TY148 };SHAPdddACourierA A @TSSHAPdddACourierA A @T]SRAPdddA PACourierA A @Tj.Task struct elements used in signal managementS1APdddA A @T<S1APdddA A @Tu9An integer flag used to indicate that a signal is pendingS1APdddA A @T2S'APdddA @Tbint sigpending;SHAPdddACourierA A @T<S1APdddA A @TZAn array that may be shared with the parent process or dynamically allocated at fork time.S'APdddA @A8 PTA8 TZT<S1APdddA  A @Tf*There is one element for each signal type.S1APdddA  A @Tx<It defines the action to be taken on receipt of the signal. S1APdddA  A @T2S'APdddA @Tmstruct signal_struct *sig;SHAPdddACourierA A @T<S1APdddA A @Tt8A bitmap indicating which signals are presently blocked.S1APdddA A @T<S1APdddA A @Tdsigset_t blocked;SHAPdddACourierA A @T? S1APdddA A @TcA structure containingSBAPddHdA A @A@. TMSBAPddHdA A @A@. T:The sigset_t bitmap identifying which signals are pending SBAPddHdpA A @A@. TL A queue used for RT processes having multiple signals of same type pendingSBAPdd,dA A @A@. TMSBAPddHdA A @A@. To struct sigpending pending;SHAPdddACourierA A @TSSHAPdddACourierA A @Ti17 struct sigpending {SHAPdddACourierA A @Tu"18 struct sigqueue *head, **tail;SHAPdddACourierA A @Tg19 sigset_t signal;SHAPdddACourierA A @TX20 };SHAPdddACourierA A @TSSHAPdddACourierA A @TVSending a signalS;APdddA PA A @T<S1APdddA A @T^The kill() function is vectored to the kernel wrapper sys_kill() which builds a siginfo packetS1APdddA A @A8 PWA8 W^TFS;APdddA  A A @TUPacket contentsS;APdddA  A A @TS signal numberS;APdddA  A A @T]signal origin (SI_USER)S;APdddA  A A @TWpid of the senderS;APdddA  A A @TKuid of the sender (so that a user shell can kill any of the user's process)S;APdddA  A A @TFS;APdddA  A A @Tf977 asmlinkage longSHAPdddACourierA A @Tq978 sys_kill(int pid, int sig)SHAPdddACourierA A @TX979 {SHAPdddACourierA A @Tl980 struct siginfo info;SHAPdddACourierA A @TW981 SHAPdddACourierA A @Tl982 info.si_signo = sig;SHAPdddACourierA A @Tj983 info.si_errno = 0;SHAPdddACourierA A @To984 info.si_code = SI_USER;SHAPdddACourierA A @Ts 985 info.si_pid = current->pid;SHAPdddACourierA A @Ts 986 info.si_uid = current->uid;SHAPdddACourierA A @TW987 SHAPdddACourierA A @T1988 return kill_something_info(sig, &info, pid);SHAPdddACourierA A @TX989 }SHAPdddACourierA A @TSSHAPdddACourierA A @T]SRAPdddA PACourierA A @TMkill_something() distinguishes between process group and single process killsSNAPdddA TimesNewRomanA A @TYSNAPdddA TimesNewRomanA A @T.target pid determines who is to receive signalSNAPdddA TimesNewRomanA A @T/0 all processes in the process group of senderSNAPdddA TimesNewRomanA A @Ti-1 all processesSNAPdddA TimesNewRomanA A @T.-n all processes in the process group of pid nSNAPdddA TimesNewRomanA A @A8 A8 -.T} +n process nSXAPdddA TimesNewRomanA  A A @A8  TZ SNAPdddA TimesNewRomanA A @T,656 static int kill_something_info(int sig, SHAPdddACourierA A @Tv# struct siginfo *info, int pid)SHAPdddACourierA A @T`657 {S'APdddA @A8A8CourierTk658 if (!pid) {S'APdddA @A8A8CourierT4659 return kill_pg_info(sig, info, current->pgrp);SHAPdddACourierA A @Tn660 } else if (pid == -1) {SHAPdddACourierA A @Ts 661 int retval = 0, count = 0;SHAPdddACourierA A @Tp662 struct task_struct * p;SHAPdddACourierA A @TW663 SHAPdddACourierA A @Ts 664 read_lock(&tasklist_lock);SHAPdddACourierA A @Tk665 for_each_task(p) {SHAPdddACourierA A @T{(666 if (p->pid > 1 && p != current) {SHAPdddACourierA A @T.667 int err = send_sig_info(sig, info, p);SHAPdddACourierA A @Tb668 ++count;SHAPdddACourierA A @Tk669 if (err != -EPERM)SHAPdddACourierA A @Tg670 retval = err;SHAPdddACourierA A @TZ671 }SHAPdddACourierA A @TY672 }SHAPdddACourierA A @Tt!673 read_unlock(&tasklist_lock);SHAPdddACourierA A @Tw$674 return count ? retval : -ESRCH;SHAPdddACourierA A @Tm675 } else if (pid < 0) {SHAPdddACourierA A @T~+676 return kill_pg_info(sig, info, -pid);SHAPdddACourierA A @T` 677 } else {SHAPdddACourierA A @T,678 return kill_proc_info(sig, info, pid);SHAPdddACourierA A @TY679 }SHAPdddACourierA A @TX680 }SHAPdddACourierA A @T<S1APdddA A @TQkill_proc_info() finds the target task struct when a single process is the targetS;APdddA PA A @T<S1APdddA A @T<634 kill_proc_info(int sig, struct siginfo *info, pid_t pid)SHAPdddACourierA A @TX635 {SHAPdddACourierA A @Tb636 int error;SHAPdddACourierA A @Tn637 struct task_struct *p;SHAPdddACourierA A @TW638 SHAPdddACourierA A @Tr639 read_lock(&tasklist_lock);SHAPdddACourierA A @Tr640 p = find_task_by_pid(pid);SHAPdddACourierA A @Tg641 error = -ESRCH;SHAPdddACourierA A @T^ 642 if (p)SHAPdddACourierA A @T}*643 error = send_sig_info(sig, info, p);SHAPdddACourierA A @Tt!644 read_unlock(&tasklist_lock);SHAPdddACourierA A @Te645 return error;SHAPdddACourierA A @TX646 }SHAPdddACourierA A @TW647 SHAPdddACourierA A @TSSHAPdddACourierA A @T-send_sig_info() is in a variety of businessesSNAPdddA TimesNewRomanA A @TYSNAPdddA TimesNewRomanA A @T'Is signal number too large or too smallSNAPdddA TimesNewRomanA A @T3Is sender / receiver / signal # a legal combinationSNAPdddA TimesNewRomanA A @T9Note that all signals are passed to handle_stop_signal()SNAPdddA TimesNewRomanA A @A8  A8 %TSSHAPdddACourierA A @T1504 send_sig_info(int sig, struct siginfo *info, S'APdddA @A81A81CourierTl struct task_struct *t)SHAPdddACourierA A @T`505 {S'APdddA @A8A8CourierTl506 unsigned long flags;SHAPdddACourierA A @T` 507 int ret;SHAPdddACourierA A @TW513 SHAPdddACourierA A @Tf514 ret = -EINVAL;SHAPdddACourierA A @Ts 515 if (sig < 0 || sig > _NSIG)SHAPdddACourierA A @Ti516 goto out_nolock;SHAPdddACourierA A @T3517 /* The somewhat baroque permissions check... */SHAPdddACourierA A @Te518 ret = -EPERM;SHAPdddACourierA A @Tu"519 if (bad_signal(sig, info, t))SHAPdddACourierA A @Ti520 goto out_nolock;SHAPdddACourierA A @TV521SHAPdddACourierA A @TD522 /* The null signal is a permissions and process existance probe.SHAPdddACourierA A @T@523 No signal is actually delivered. Same goes for zombies. */SHAPdddACourierA A @T` 524 ret = 0;SHAPdddACourierA A @Tl525 if (!sig || !t->sig)SHAPdddACourierA A @Ti526 goto out_nolock;SHAPdddACourierA A @TW527 SHAPdddACourierA A @T0528 spin_lock_irqsave(&t->sigmask_lock, flags);SHAPdddACourierA A @Ts 529 handle_stop_signal(sig, t);SHAPdddACourierA A @TV530SHAPdddACourierA A @T^ SRAPdddA PACourierA A @T=531 /* Optimize away the signal, if it's a signal that can beSHAPdddACourierA A @T:532 handled immediately (ie non-blocked and untraced) andSHAPdddACourierA A @T;533 that is ignored (either explicitly or by default). */SHAPdddACourierA A @TW534 SHAPdddACourierA A @Ts 535 if (ignored_signal(sig, t))SHAPdddACourierA A @Tb536 goto out;SHAPdddACourierA A @TW537 SHAPdddACourierA A @TSSHAPdddACourierA A @Tqueuing of multiple signals of the same type may occur while delivery is blocked but only if the signal is real-time. Blocked NRT signals are idempotent. SNAPdddA TimesNewRomanA A @A8 UYA8 YTSSHAPdddACourierA A @T=538 /* Support queueing exactly one non-rt signal, so that weSHAPdddACourierA A @T9539 can get more detailed information about the cause ofSHAPdddACourierA A @Tf540 the signal. */SHAPdddACourierA A @T@541 if (sig < SIGRTMIN && sigismember(&t->pending.signal, sig))SHAPdddACourierA A @Tb542 goto out;SHAPdddACourierA A @TW543 SHAPdddACourierA A @TYSNAPdddA TimesNewRomanA A @TPFinally deliver_signal() actually leads in the direction in which we want to go.SNAPdddA TimesNewRomanA A @TSSHAPdddACourierA A @Tz'544 ret = deliver_signal(sig, info, t);SHAPdddACourierA A @T[545 out:SHAPdddACourierA A @T4546 spin_unlock_irqrestore(&t->sigmask_lock, flags);SHAPdddACourierA A @Tb547 out_nolock:SHAPdddACourierA A @Tb552 return ret;SHAPdddACourierA A @TX553 }SHAPdddACourierA A @TW554 SHAPdddACourierA A @TSSHAPdddACourierA A @TaThis checks the authority of the sender (current) to send the specified signal to the target (t).SNAPdddA TimesNewRomanA A @A8 (1A8 ]`TSSHAPdddACourierA A @T2308 int bad_signal(int sig, struct siginfo *info, S'APdddA @A82A82CourierTm struct task_struct *t)SHAPdddACourierA A @T`309 {S'APdddA @A8A8CourierTN310 return (!info || ((unsigned long)info != 1 && SI_FROMUSER(info)))SHAPdddACourierA A @T=311 && ((sig != SIGCONT) || (current->session != t->session))SHAPdddACourierA A @T<312 && (current->euid ^ t->suid) && (current->euid ^ t->uid)SHAPdddACourierA A @T:313 && (current->uid ^ t->suid) && (current->uid ^ t->uid)SHAPdddACourierA A @Tm314 && !capable(CAP_KILL);SHAPdddACourierA A @TX315 }SHAPdddACourierA A @TSSHAPdddACourierA A @T|handle_stop_signal() is concerned with dequeuing queued signals that might undo the work of the one about to be delivered.. SXAPdddA PA TimesNewRomanA A @TYSNAPdddA TimesNewRomanA A @TSSHAPdddACourierA A @TB380 static void handle_stop_signal(int sig, struct task_struct *t)SHAPdddACourierA A @T`381 {S'APdddA @A8A8CourierTe382 switch (sig) {SHAPdddACourierA A @Ts 383 case SIGKILL: case SIGCONT:SHAPdddACourierA A @T~+384 /* Wake up the process if stopped. */SHAPdddACourierA A @Tv#385 if (t->state == TASK_STOPPED)SHAPdddACourierA A @Tm386 wake_up_process(t);SHAPdddACourierA A @Tj387 t->exit_code = 0;SHAPdddACourierA A @Tw$388 rm_sig_from_queue(SIGSTOP, t);SHAPdddACourierA A @Tw$389 rm_sig_from_queue(SIGTSTP, t);SHAPdddACourierA A @Tw$390 rm_sig_from_queue(SIGTTOU, t);SHAPdddACourierA A @Tw$391 rm_sig_from_queue(SIGTTIN, t);SHAPdddACourierA A @T_ 392 break;SHAPdddACourierA A @TW393 SHAPdddACourierA A @Ts 394 case SIGSTOP: case SIGTSTP:SHAPdddACourierA A @Ts 395 case SIGTTIN: case SIGTTOU:SHAPdddACourierA A @T2396 /* If we're stopping again, cancel SIGCONT */SHAPdddACourierA A @Tw$397 rm_sig_from_queue(SIGCONT, t);SHAPdddACourierA A @T^ 398 break;SHAPdddACourierA A @TY399 }SHAPdddACourierA A @TX400 }SHAPdddACourierA A @TSSHAPdddACourierA A @T~%deliver_signal() calls send_signal() SNAPdddA TimesNewRomanA A @TMIf that call succeeds and the delivery of the present signal is not blocked SNAPdddA TimesNewRomanA A @T`then it is necessary to attempt to wake up the target process so that the signal can be receivedSNAPdddA TimesNewRomanA A @TYSNAPdddA TimesNewRomanA A @Tz'493 static int deliver_signal(int sig, SHAPdddACourierA A @T/ struct siginfo *info, struct task_struct *t)SHAPdddACourierA A @TX494 {SHAPdddACourierA A @T6495 int retval = send_signal(sig, info, &t->pending);SHAPdddACourierA A @TW496 SHAPdddACourierA A @T3497 if (!retval && !sigismember(&t->blocked, sig))SHAPdddACourierA A @Tk498 signal_wake_up(t);SHAPdddACourierA A @TW499 SHAPdddACourierA A @Te500 return retval;SHAPdddACourierA A @TX501 }SHAPdddACourierA A @TSSHAPdddACourierA A @TOsend_signal() contains a rather complex body of code that deals with RT signalsSXAPdddA PA TimesNewRomanA A @TwThen it calls sigaddset() ... SNAPdddA TimesNewRomanA A @TYSNAPdddA TimesNewRomanA A @T$402 static int send_signal(int sig, S'APdddA @A8$A8$CourierT4 struct siginfo *info, struct sigpending *signals)SHAPdddACourierA A @T`403 {S'APdddA @A8A8CourierTt!404 struct sigqueue * q = NULL;SHAPdddACourierA A @TW405 SHAPdddACourierA A @TSSHAPdddACourierA A @T6-- Big mess of stuff relating to RT signals deleted --S'APdddA @A86A86CourierTSSHAPdddACourierA A @TW450 SHAPdddACourierA A @Tz'451 sigaddset(&signals->signal, sig);SHAPdddACourierA A @Tb452 return 0;SHAPdddACourierA A @TX453 }SHAPdddACourierA A @TSSHAPdddACourierA A @T4sigaddset() is where the bit finally gets flipped. SNAPdddA TimesNewRomanA A @A8 %A8 %3TYSNAPdddA TimesNewRomanA A @T831 static inline void sigaddset(sigset_t *set, int _sig)SHAPdddACourierA A @TW32 {SHAPdddACourierA A @Tt!33 unsigned long sig = _sig - 1;SHAPdddACourierA A @Tl34 if (_NSIG_WORDS == 1)SHAPdddACourierA A @Tr35 set->sig[0] |= 1UL << sig;SHAPdddACourierA A @T[36 elseSHAPdddACourierA A @T>37 set->sig[sig / _NSIG_BPW] |= 1UL << (sig % _NSIG_BPW);SHAPdddACourierA A @TW38 }SHAPdddACourierA A @TU39SHAPdddACourierA A @TSSHAPdddACourierA A @T|The objective here is to:SXAPdddA PA TimesNewRomanA A @TYSNAPdddA TimesNewRomanA A @T:Force a reschedule if the target is running on another CPUSNAPdddA TimesNewRomanA A @TWake up the target if it is in an interruptible sleep... (this is where the problem of interruptible /restartable syscalls arises)SNAPdddA TimesNewRomanA A @TIIf the target is UNINTERRUPTIBLE or waiting to RUN nothing happens here. SNAPdddA TimesNewRomanA A @TYSNAPdddA TimesNewRomanA A @T<466 static inline void signal_wake_up(struct task_struct *t)SHAPdddACourierA A @TX467       !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVXYZ{SHAPdddACourierA A @Tj468 t->sigpending = 1;SHAPdddACourierA A @TW469 SHAPdddACourierA A @Th470 #ifdef CONFIG_SMPSHAPdddACourierA A @TZ471 /*SHAPdddACourierA A @T1472 * If the task is running on a different CPU SHAPdddACourierA A @T2473 * force a reschedule on the other CPU to makeSHAPdddACourierA A @T{(474 * it notice the new signal quickly.SHAPdddACourierA A @TX475 *SHAPdddACourierA A @T;476 * The code below is a tad loose and might occasionallySHAPdddACourierA A @T8477 * kick the wrong CPU if we catch the process in theSHAPdddACourierA A @T8478 * process of changing - but no harm is done by thatSHAPdddACourierA A @T=479 * other than doing an extra (lightweight) IPI interrupt.SHAPdddACourierA A @TZ480 */SHAPdddACourierA A @Tr481 spin_lock(&runqueue_lock);SHAPdddACourierA A @T?482 if (task_has_cpu(t) && t->processor != smp_processor_id())SHAPdddACourierA A @T{(483 smp_send_reschedule(t->processor);SHAPdddACourierA A @Tt!484 spin_unlock(&runqueue_lock);SHAPdddACourierA A @Tn485 #endif /* CONFIG_SMP */SHAPdddACourierA A @TW486 SHAPdddACourierA A @T|)487 if (t->state & TASK_INTERRUPTIBLE) {SHAPdddACourierA A @Tl488 wake_up_process(t);SHAPdddACourierA A @T_ 489 return;SHAPdddACourierA A @TY490 }SHAPdddACourierA A @TX491 }SHAPdddACourierA A @TSSHAPdddACourierA A @T]SRAPdddA PACourierA A @TbKernel handler for sigaction() -- note use of old_sigaction parms.. but kernel uses new internallyS1APdddA A @T= S1APdddA A @Ti-Input parameters (struct sigaction) specifiesS1APdddA A @Tk/Address of signal handler or SIG_IGN or SIG_DFLS1APdddA A @TKsa_mask identifies which signals are to be blocked during signal processingS1APdddA A @Tw;sa_flags provides other oddball modifiers discussed earlierS1APdddA A @TH S1APdddA A @T;123 sys_sigaction(int sig, const struct old_sigaction *act,SHAPdddACourierA A @Tr124 struct old_sigaction *oact)SHAPdddACourierA A @TX125 {SHAPdddACourierA A @Tz'126 struct k_sigaction new_ka, old_ka;SHAPdddACourierA A @T` 127 int ret;SHAPdddACourierA A @TV128SHAPdddACourierA A @TSSHAPdddACourierA A @Tx<If a user passed an action structure handler for sigaction()S1APdddA A @TT SHAPdddACourierA A @Ta129 if (act) {SHAPdddACourierA A @Tj130 old_sigset_t mask;SHAPdddACourierA A @T7131 if (verify_area(VERIFY_READ, act, sizeof(*act)) ||SHAPdddACourierA A @T;132 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||SHAPdddACourierA A @T;133 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))SHAPdddACourierA A @Th134 return -EFAULT;SHAPdddACourierA A @T4135 __get_user(new_ka.sa.sa_flags, &act->sa_flags);SHAPdddACourierA A @Tx%136 __get_user(mask, &act->sa_mask);SHAPdddACourierA A @T}*137 siginitset(&new_ka.sa.sa_mask, mask);SHAPdddACourierA A @TX138 }SHAPdddACourierA A @TW139 SHAPdddACourierA A @TSSHAPdddACourierA A @Ty/do_sigaction() actually does the the real work S1APdddA A @A8.TSSHAPdddACourierA A @TN140 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);SHAPdddACourierA A @TSSHAPdddACourierA A @TGif do_sigaction worked and user passed an old pointer do the copy back.S1APdddA A @TSSHAPdddACourierA A @Tj142 if (!ret && oact) {SHAPdddACourierA A @T9143 if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||SHAPdddACourierA A @T<144 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||SHAPdddACourierA A @T<145 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))SHAPdddACourierA A @Th146 return -EFAULT;SHAPdddACourierA A @T5147 __put_user(old_ka.sa.sa_flags, &oact->sa_flags);SHAPdddACourierA A @T:148 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);SHAPdddACourierA A @TX149 }SHAPdddACourierA A @TW150 SHAPdddACourierA A @Tb151 return ret;SHAPdddACourierA A @TX152 }SHAPdddACourierA A @TW153 SHAPdddACourierA A @T<S1APdddA A @Tk1009 intSXAPdddA PA Courier (Tur)A A @TX1010 do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact)SNAPdddA Courier (Tur)A A @T_1011 {SNAPdddA Courier (Tur)A A @Tu1012 struct k_sigaction *k;SNAPdddA Courier (Tur)A A @T^1013 SNAPdddA Courier (Tur)A A @TYSNAPdddA Courier (Tur)A A @TVerify signal number is legal.SNAPdddA TimesNewRomanA A @A8TYSNAPdddA Courier (Tur)A A @T{"1014 if (sig < 1 || sig > _NSIG ||SNAPdddA Courier (Tur)A A @T51015 (act && (sig == SIGKILL || sig == SIGSTOP)))SNAPdddA Courier (Tur)A A @To1016 return -EINVAL;SNAPdddA Courier (Tur)A A @T^1017 SNAPdddA Courier (Tur)A A @TYSNAPdddA Courier (Tur)A A @T.Note that internally the indices are 0 origin.SNAPdddA TimesNewRomanA A @A8.TYSNAPdddA Courier (Tur)A A @T&1018 k = ¤t->sig->action[sig-1];SNAPdddA Courier (Tur)A A @T]1019SNAPdddA Courier (Tur)A A @T(1020 spin_lock(¤t->sig->siglock);SNAPdddA Courier (Tur)A A @T^1021 SNAPdddA Courier (Tur)A A @TYSNAPdddA Courier (Tur)A A @T$Save copy of old action if required.SNAPdddA TimesNewRomanA A @A8$TYSNAPdddA TimesNewRomanA A @Tg1022 if (oact)SNAPdddA Courier (Tur)A A @Tk1023 *oact = *k;SNAPdddA Courier (Tur)A A @T^1024 SNAPdddA Courier (Tur)A A @TYSNAPdddA Courier (Tur)A A @T"Note that this is a structure copySNAPdddA TimesNewRomanA A @A8"TYSNAPdddA Courier (Tur)A A @Th1025 if (act) {SNAPdddA Courier (Tur)A A @Tj1026 *k = *act;SNAPdddA Courier (Tur)A A @TQ1027 sigdelsetmask(&k->sa.sa_mask, sigmask(SIGKILL) | sigmask(SIGSTOP));S'APdddA @A8QA!8Q Courier (Tur)TYSNAPdddA Courier (Tur)A A @TFinally set up the handler..SXAPdddA PA TimesNewRomanA A @A8TYSNAPdddA Courier (Tur)A A @T^1028 SNAPdddA Courier (Tur)A A @T`1029 /*SNAPdddA Courier (Tur)A A @Tn1030 * POSIX 3.3.1.3:SNAPdddA Courier (Tur)A A @T@1031 * "Setting a signal action to SIG_IGN for a signal that isSNAPdddA Courier (Tur)A A @T@1032 * pending shall cause the pending signal to be discarded,SNAPdddA Courier (Tur)A A @T'1033 * whether or not it is blocked."SNAPdddA Courier (Tur)A A @T_1034 *SNAPdddA Courier (Tur)A A @T@1035 * "Setting a signal action to SIG_DFL for a signal that isSNAPdddA Courier (Tur)A A @TA1036 * pending and whose default action is to ignore the signalSNAPdddA Courier (Tur)A A @TB1037 * (for example, SIGCHLD), shall cause the pending signal toSNAPdddA Courier (Tur)A A @T41038 * be discarded, whether or not it is blocked"SNAPdddA Courier (Tur)A A @T_1039 *SNAPdddA Courier (Tur)A A @TB1040 * Note the silly behaviour of SIGCHLD: SIG_IGN means that theSNAPdddA Courier (Tur)A A @T>1041 * signal isn't actually ignored, but does automatic childSNAPdddA Courier (Tur)A A @TB1042 * reaping, while SIG_DFL is explicitly said by POSIX to forceSNAPdddA Courier (Tur)A A @Ty 1043 * the signal to be ignored.SNAPdddA Courier (Tur)A A @T`1044 */SNAPdddA Courier (Tur)A A @T^1045 SNAPdddA Courier (Tur)A A @T}$1046 if (k->sa.sa_handler == SIG_IGNSNAPdddA Courier (Tur)A A @T'1047 || (k->sa.sa_handler == SIG_DFLSNAPdddA Courier (Tur)A A @Tv1048 && (sig == SIGCONT ||SNAPdddA Courier (Tur)A A @Tr1049 sig == SIGCHLD ||SNAPdddA Courier (Tur)A A @Tu1050 sig == SIGWINCH))) {SNAPdddA Courier (Tur)A A @T-1051 spin_lock_irq(¤t->sigmask_lock);SNAPdddA Courier (Tur)A A @T+1052 if (rm_sig_from_queue(sig, current))SNAPdddA Courier (Tur)A A @T|#1053 recalc_sigpending(current);SNAPdddA Courier (Tur)A A @T/1054 spin_unlock_irq(¤t->sigmask_lock);SNAPdddA Courier (Tur)A A @T`1055 }SNAPdddA Courier (Tur)A A @T_1056 }SNAPdddA Courier (Tur)A A @T^1057 SNAPdddA Courier (Tur)A A @T)1058 spin_unlock(¤t->sig->siglock);SNAPdddA Courier (Tur)A A @Tg1059 return 0;SNAPdddA Courier (Tur)A A @T_1060 }SNAPdddA Courier (Tur)A A @T^1061 SNAPdddA Courier (Tur)A A @TYSNAPdddA Courier (Tur)A A @TsDelivery (receipt) of signalsSKAPdddA PAA A @TLSAAPdddAA A @TYSNAPdddA TimesNewRomanA A @TLDelivery of signals to application handlers is a bit complicated because ...SNAPdddA TimesNewRomanA A @TYSNAPdddA TimesNewRomanA A @T,The delivery setup takes place in the kernelSNAPdddA TimesNewRomanA A @T~%The signal handlers run in user mode SNAPdddA TimesNewRomanA A @TLThe signal handlers must "return" to the kernel to effect unblock when done.SNAPdddA TimesNewRomanA A @TYSNAPdddA TimesNewRomanA A @TxBasic idea is moderately simpleSNAPdddA TimesNewRomanA A @TYSNAPdddA TimesNewRomanA A @TLAdd context to the kernel stack so that when next return to user mode occursSNAPdddA TimesNewRomanA A @TRreturn is to the signal handler instead of the point from which kernel was enteredSNAPdddA TimesNewRomanA A @T@return from the signal handler points to a sigreturn system callSNAPdddA TimesNewRomanA A @A8 +4A8 4@TcSXAPdddA TimesNewRomanA  A A @TFIn sigreturn unblock signals and restore the state of the kernel stackSXAPdddA TimesNewRomanA  A A @A8  TcSXAPdddA TimesNewRomanA  A A @T%As ususal the devil is in the detailsSXAPdddA TimesNewRomanA  A A @T@Particularly the fact that signal handlers can make system callsSXAPdddA TimesNewRomanA  A A @TPThus potentially wiping out the saved user context which is on the kernel stack.SXAPdddA TimesNewRomanA  A A @TcSXAPdddA TimesNewRomanA  A A @TKEntry to signal delivery is just before the interrupt return (restore_all)SXAPdddA TimesNewRomanA  A A @TcSXAPdddA TimesNewRomanA  A A @Tasignal_return:SHAPdddACourierA A @TS sti # we can get here from an interrupt handlerSHAPdddACourierA A @Tx% testl $(VM_MASK),EFLAGS(%esp)SHAPdddACourierA A @Ti movl %esp,%eaxSHAPdddACourierA A @Tp jne v86_signal_returnSHAPdddACourierA A @Ti xorl %edx,%edxSHAPdddACourierA A @Tv# call SYMBOL_NAME(do_signal)SHAPdddACourierA A @Tj jmp restore_allSHAPdddACourierA A @T]SRAPdddACourierA  A A @TKEntry to signal delivery is just before the interrupt return (restore_all)SXAPdddA TimesNewRomanA  A A @TcSXAPdddA TimesNewRomanA  A A @TrParameters are SXAPdddA TimesNewRomanA  A A @TIEAX a pointer to the user mode registers that were about to be restored SXAPdddA TimesNewRomanA  A A @A8 T2EDX null here but can be a signal bit map pointerSXAPdddA TimesNewRomanA  A A @A8 2TcSXAPdddA TimesNewRomanA  A A @Tn SbAPdddA PA TimesNewRomanA  A A @T]583 SNAPdddA Courier (Tur)A A @T9584 int do_signal(struct pt_regs *regs, sigset_t *oldset)SNAPdddA Courier (Tur)A A @T^585 {SNAPdddA Courier (Tur)A A @Tl586 siginfo_t info;SNAPdddA Courier (Tur)A A @Tt587 struct k_sigaction *ka;SNAPdddA Courier (Tur)A A @T]588 SNAPdddA Courier (Tur)A A @TYSNAPdddA Courier (Tur)A A @TaLow order bits of the CS register at interrupt time have the privilege level at time of interruptSXAPdddA TimesNewRomanA  A A @TIIf this call is just prior to return from interrupt, the value will be 3.SXAPdddA TimesNewRomanA  A A @A8 ?CTcSXAPdddA TimesNewRomanA  A A @T_589 /*SNAPdddA Courier (Tur)A A @T/590 * We want the common case to go fast, whichSNAPdddA Courier (Tur)A A @T2591 * is why we may in certain cases get here fromSNAPdddA Courier (Tur)A A @T5592 * kernel mode. Just return without doing anythingSNAPdddA Courier (Tur)A A @Te 593 * if so.SNAPdddA Courier (Tur)A A @T_594 */SNAPdddA Courier (Tur)A A @Tv595 if ((regs->xcs & 3) != 3)SNAPdddA Courier (Tur)A A @Th596 return 1;SNAPdddA Courier (Tur)A A @T]597 SNAPdddA Courier (Tur)A A @TcSXAPdddA TimesNewRomanA  A A @T`If caller didn't provide an oldset pointer used the blocked signal vector of the running processSXAPdddA TimesNewRomanA  A A @A8 "TcSXAPdddA TimesNewRomanA  A A @Ti598 if (!oldset)SNAPdddA Courier (Tur)A A @Tz!599 oldset = ¤t->blocked;SNAPdddA Courier (Tur)A A @T]600 SNAPdddA Courier (Tur)A A @TYSNAPdddA Courier (Tur)A A @T7This loop is the core of the signal delivery mechansim.SXAPdddA TimesNewRomanA  A A @TcSXAPdddA TimesNewRomanA  A A @T0One iteration is made for each signal delivered.SXAPdddA TimesNewRomanA  A A @T(If dequeue_signal returns 0 we are done.SXAPdddA TimesNewRomanA  A A @A8 T?If not, signr contains the number of the signal to be deliveredSXAPdddA TimesNewRomanA  A A @A8  TNdequeue_signal also calls collect_signal() which resets the signal pending bitSXAPdddA TimesNewRomanA  A A @A8 A8 *A8 *NTcSXAPdddA TimesNewRomanA  A A @Tg601 for (;;) {SNAPdddA Courier (Tur)A A @Ts602 unsigned long signr;SNAPdddA Courier (Tur)A A @T]603 SNAPdddA Courier (Tur)A A @T,604 spin_lock_irq(¤t->sigmask_lock);SNAPdddA Courier (Tur)A A @T7605 signr = dequeue_signal(¤t->blocked, &info);SNAPdddA Courier (Tur)A A @T.606 spin_unlock_irq(¤t->sigmask_lock);SNAPdddA Courier (Tur)A A @T]607 SNAPdddA Courier (Tur)A A @Tj608 if (!signr)SNAPdddA Courier (Tur)A A @Tf 609 break;SNAPdddA Courier (Tur)A A @T]610 SNAPdddA Courier (Tur)A A @TYSNAPdddA Courier (Tur)A A @T%Debugger related stuff we will ignoreSbAPdddA PA TimesNewRomanA  A A @TcSXAPdddA TimesNewRomanA  A A @T?611 if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {SNAPdddA Courier (Tur)A A @T{"612 /* Let the debugger run. */SNAPdddA Courier (Tur)A A @T{"613 current->exit_code = signr;SNAPdddA Courier (Tur)A A @T~%614 current->state = TASK_STOPPED;SNAPdddA Courier (Tur)A A @Tl :S'APdddA @A8 A!8  Courier (Tur)T7 :S'APdddA @T2S'APdddA @TTSet ka to point to this process's signal_struct so that we can tell how to handle itS'APdddA @A8 A8 TA8 "0T<S1APdddA  A @T*643 ka = ¤t->sig->action[signr-1];SNAPdddA Courier (Tur)A A @TYSNAPdddA Courier (Tur)A A @Tz:As noted last time SIG_IGN doesn't mean ignore for SIGCHLDS'APdddA @A8 :Ts)sys_wait4 is use to reap zombie children.S1APdddA  A @A8  )TcSXAPdddA Courier (Tur)A  A A @T)644 if (ka->sa.sa_handler == SIG_IGN) {SNAPdddA Courier (Tur)A A @Tu645 if (signr != SIGCHLD)SNAPdddA Courier (Tur)A A @Tj646 continue;SNAPdddA Courier (Tur)A A @T-647 /* Check for SIGCHLD: it's special. */SNAPdddA Courier (Tur)A A @T5648 while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)SNAPdddA Courier (Tur)A A @Tn649 /* nothing */;SNAPdddA Courier (Tur)A A @Tj650 continue;SNAPdddA Courier (Tur)A A @T`651 }SNAPdddA Courier (Tur)A A @T\652SNAPdddA Courier (Tur)A A @TYSNAPdddA Courier (Tur)A A @TDefault handling is done here... the exit_code for a process that is terminated by the default actions contains the signal numberS'APdddA @TZ SNAPdddA Courier (Tur)A A @T)653 if (ka->sa.sa_handler == SIG_DFL) {SNAPdddA Courier (Tur)A A @Tv654 int exit_code = signr;SNAPdddA Courier (Tur)A A @T]655 SNAPdddA Courier (Tur)A A @TYSNAPdddA TimesNewRomanA A @TYinit (process 1) is a special process: it doesn't get signals it doesn't want to handle. SNAPdddA TimesNewRomanA A @T>Thus you cannot kill init even with a SIGKILL even by mistake.SNAPdddA TimesNewRomanA A @T2S'APdddA @T3656 /* Init gets no signals it doesn't want. */SNAPdddA Courier (Tur)A A @Tv657 if (current->pid == 1)SNAPdddA Courier (Tur)A A @Tj658 continue;SNAPdddA Courier (Tur)A A @T]659 SNAPdddA Courier (Tur)A A @TYSNAPdddA Courier (Tur)A A @Tu+Default actions are executed in this switchS1APdddA PA @A8 +T;The continue statements go to the end of the for (;;) loop S1APdddA  A @A8  TcSXAPdddA Courier (Tur)A  A A @Tp660 switch (signr) {SNAPdddA Courier (Tur)A A @T1661 case SIGCONT: case SIGCHLD: case SIGWINCH:SNAPdddA Courier (Tur)A A @Tj662 continue;SNAPdddA Courier (Tur)A A @T\663SNAPdddA Courier (Tur)A A @T2S'APdddA @TPThank you POSIX:S'APdddA @A8 TA process group is not ophaned as long as there is a process in the group that has a parent in a different process group but in the same session. S1APdddA  A @A8 A8 akA8 TZ SNAPdddA Courier (Tur)A A @T0664 case SIGTSTP: case SIGTTIN: case SIGTTOU:SNAPdddA Courier (Tur)A A @T,665 if (is_orphaned_pgrp(current->pgrp))SNAPdddA Courier (Tur)A A @Tk666 continue;SNAPdddA Courier (Tur)A A @Tn667 /* FALLTHRU */SNAPdddA Courier (Tur)A A @T]668 SNAPdddA Courier (Tur)A A @To669 case SIGSTOP: {SNAPdddA Courier (Tur)A A @T{"670 struct signal_struct *sig;SNAPdddA Courier (Tur)A A @T&671 current->state = TASK_STOPPED;SNAPdddA Courier (Tur)A A @T|#672 current->exit_code = signr;SNAPdddA Courier (Tur)A A @T|#673 sig = current->p_pptr->sig;SNAPdddA Courier (Tur)A A @T8674 if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags SNAPdddA Courier (Tur)A A @Tn & SA_NOCLDSTOP))SNAPdddA Courier (Tur)A A @T)675 notify_parent(current, SIGCHLD);SNAPdddA Courier (Tur)A A @Tl676 schedule();SNAPdddA Courier (Tur)A A @Tj677 continue;SNAPdddA Courier (Tur)A A @Ta678 }SNAPdddA Courier (Tur)A A @T]679 SNAPdddA Courier (Tur)A A @TYSNAPdddA Courier (Tur)A A @Tz,A process that reaches this point is doomed.S'APdddA @A8 %A8 %,TcSXAPdddA Courier (Tur)A  A A @T/680 case SIGQUIT: case SIGILL: case SIGTRAP:SNAPdddA Courier (Tur)A A @T/681 case SIGABRT: case SIGFPE: case SIGSEGV:SNAPdddA Courier (Tur)A A @T/682 case SIGBUS: case SIGSYS: case SIGXCPU: SNAPdddA Courier (Tur)A A @Ti case SIGXFSZ:SNAPdddA Courier (Tur)A A @T~%683 if (do_coredump(signr, regs))SNAPdddA Courier (Tur)A A @Tt684 exit_code |= 0x80;SNAPdddA Courier (Tur)A A @Tk685 /* FALLTHRU */SNAPdddA Courier (Tur)A A @T]686 SNAPdddA Courier (Tur)A A @Tg687 default:SNAPdddA Courier (Tur)A A @T2688 sigaddset(¤t->pending.signal, signr);SNAPdddA Courier (Tur)A A @T{"689 recalc_sigpending(current);SNAPdddA Courier (Tur)A A @T~%690 current->flags |= PF_SIGNALED;SNAPdddA Courier (Tur)A A @Ts691 do_exit(exit_code);SNAPdddA Courier (Tur)A A @Tm692 /* NOTREACHED */SNAPdddA Courier (Tur)A A @Tx693 } /* switch() */S'APdddA @A8A!8 Courier (Tur)Ts694 } /* if (SIG_DFL) */SNAPdddA Courier (Tur)A A @T]695 SNAPdddA Courier (Tur)A A @TYSNAPdddA Courier (Tur)A A @T5Reaching here means a signal handler will be invoked.S1APdddA PA @A8 5T`$This first part is debugger related S1APdddA  A @TcSXAPdddA Courier (Tur)A  A A @T7696 /* Reenable any watchpoints before delivering theSNAPdddA Courier (Tur)A A @T9697 * signal to user space. The processor register willSNAPdddA Courier (Tur)A A @T5698 * have been cleared if the watchpoint triggeredSNAPdddA Courier (Tur)A A @Ts699 * inside the kernel.SNAPdddA Courier (Tur)A A @Ta700 */SNAPdddA Courier (Tur)A A @T,701 __asm__("movl %0,%%db7" : : "r" ( SNAPdddA Courier (Tur)A A @T{" current->thread.debugreg[7]));SNAPdddA Courier (Tur)A A @T2S'APdddA @TRThe return here ensures that only one signal will be handled per call to do_signalS'APdddA @A8 RA8 "%TNAccording to the book this relates to handling RT signals in the proper orderS1APdddA  A @TcSXAPdddA Courier (Tur)A  A A @T]702 SNAPdddA Courier (Tur)A A @T0703 /* Whee! Actually deliver the signal. */SNAPdddA Courier (Tur)A A @T4704 handle_signal(signr, ka, &info, oldset, regs);SNAPdddA Courier (Tur)A A @Th705 return 1;SNAPdddA Courier (Tur)A A @T^706 }SNAPdddA Courier (Tur)A A @T]707 SNAPdddA Courier (Tur)A A @TYSNAPdddA Courier (Tur)A A @TSAt last, here is the use for the mysterious orig_eax from the system call material.S'APdddA @A8 STcSXAPdddA Courier (Tur)A  A A @T)708 /* Did we come from a system call? */SNAPdddA Courier (Tur)A A @Tw709 if (regs->orig_eax >= 0) {SNAPdddA Courier (Tur)A A @T9710 /* Restart the system call - no handlers present */SNAPdddA Courier (Tur)A A @T)711 if (regs->eax == -ERESTARTNOHAND ||SNAPdddA Courier (Tur)A A @T|#712 regs->eax == -ERESTARTSYS ||SNAPdddA Courier (Tur)A A @T&713 regs->eax == -ERESTARTNOINTR) {SNAPdddA Courier (Tur)A A @T{"714 regs->eax = regs->orig_eax;SNAPdddA Courier (Tur)A A @To715 regs->eip -= 2;SNAPdddA Courier (Tur)A A @T_716 }SNAPdddA Courier (Tur)A A @T^717 }SNAPdddA Courier (Tur)A A @Tf 718 return 0;SNAPdddA Courier (Tur)A A @T^719 }SNAPdddA Courier (Tur)A A @T]720 SNAPdddA Courier (Tur)A A @TYSNAPdddA Courier (Tur)A A @TcSXAPdddA PA Courier (Tur)A A @TVThe registers being manipulated here are the user registers saved on the kernel stack S'APdddA @A8 VTcSXAPdddA Courier (Tur)A  A A @Th537 static voidSNAPdddA Courier (Tur)A A @T<538 handle_signal(unsigned long sig, struct k_sigaction *ka,SNAPdddA Courier (Tur)A A @T>539 siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)SNAPdddA Courier (Tur)A A @T_540 {SNAPdddA Courier (Tur)A A @T~%541 /* Are we from a system call? */SNAPdddA Courier (Tur)A A @Tx542 if (regs->orig_eax >= 0) {SNAPdddA Courier (Tur)A A @T1543 /* If so, check system call restarting.. */SNAPdddA Courier (Tur)A A @Ts544 switch (regs->eax) {SNAPdddA Courier (Tur)A A @Tt545 case -ERESTARTNOHAND:SNAPdddA Courier (Tur)A A @Ts546 regs->eax = -EINTR;SNAPdddA Courier (Tur)A A @Tf 547 break;SNAPdddA Courier (Tur)A A @T]548 SNAPdddA Courier (Tur)A A @Tq549 case -ERESTARTSYS:SNAPdddA Courier (Tur)A A @T-550 if (!(ka->sa.sa_flags & SA_RESTART)) {SNAPdddA Courier (Tur)A A @Tt551 regs->eax = -EINTR;SNAPdddA Courier (Tur)A A @Tg552 break;SNAPdddA Courier (Tur)A A @Ta553 }SNAPdddA Courier (Tur)A A @Tp554 /* fallthrough */SNAPdddA Courier (Tur)A A @TYSNAPdddA Courier (Tur)A A @TYSNAPdddA Courier (Tur)A A @T|.Here we put the system call number back in EAXS'APdddA @A8 +A8 +.TIEIP is decremented so that it now points back at the int 0x80 instructionS1APdddA  A @A8 5A8 =ITNWhen return to user mode occurs, the system call will be immediately reissued.S1APdddA  A @TcSXAPdddA Courier (Tur)A  A A @Tt555 case -ERESTARTNOINTR:SNAPdddA Courier (Tur)A A @T{"556 regs->eax = regs->orig_eax;SNAPdddA Courier (Tur)A A @To557 regs->eip -= 2;SNAPdddA Courier (Tur)A A @T`558 }SNAPdddA Courier (Tur)A A @T_559 }SNAPdddA Courier (Tur)A A @T]560 SNAPdddA Courier (Tur)A A @Ty 561 /* Set up the stack frame */SNAPdddA Courier (Tur)A A @T&562 if (ka->sa.sa_flags & SA_SIGINFO)SNAPdddA Courier (Tur)A A @T2563 setup_rt_frame(sig, ka, info, oldset, regs);SNAPdddA Courier (Tur)A A @Tb 564 elseSNAPdddA Courier (Tur)A A @T)565 setup_frame(sig, ka, oldset, regs);SNAPdddA Courier (Tur)A A @T\566SNAPdddA Courier (Tur)A A @TcSXAPdddA PA Courier (Tur)A A @Tt4Here is where ONESHOT handlers get reset to SIG_DFL S'APdddA @A8 4TZ SNAPdddA Courier (Tur)A A @T&567 if (ka->sa.sa_flags & SA_ONESHOT)SNAPdddA Courier (Tur)A A @T{"568 ka->sa.sa_handler = SIG_DFL;SNAPdddA Courier (Tur)A A @T]569 SNAPdddA Courier (Tur)A A @TYSNAPdddA Courier (Tur)A A @TYSNAPdddA Courier (Tur)A A @Tt4Unless the SA_NODEFER flag is set block, delivery ofS'APdddA @A8 4T`$those signals defined in the sa_maskS1APdddA  A @TWthe signal being delivered.S1APdddA  A @T<S1APdddA  A @T+570 if (!(ka->sa.sa_flags & SA_NODEFER)) {SXAPdddA Courier (Tur)A  A A @T,571 spin_lock_irq(¤t->sigmask_lock);SNAPdddA Courier (Tur)A A @T4572 sigorsets(¤t->blocked,¤t->blocked,SNAPdddA Courier (Tur)A A @Tr &ka->sa.sa_mask);SNAPdddA Courier (Tur)A A @T'573 sigaddset(¤t->blocked,sig);SNAPdddA Courier (Tur)A A @Tz!574 recalc_sigpending(current);SNAPdddA Courier (Tur)A A @T.575 spin_unlock_irq(¤t->sigmask_lock);SNAPdddA Courier (Tur)A A @T_576 }SNAPdddA Courier (Tur)A A @T^577 }SNAPdddA Courier (Tur)A A @TYSNAPdddA Courier (Tur)A A @TQThis is where we muck around with the stack frame to address the following issuesS'APdddA @A8 QT<S1APdddA  A @Tx<Save the user mode context which is now on the kernel stack S1APdddA  A @Ty=Set up a context that will make us return to the user handlerS1APdddA  A @TKEnsure that the return from the user handler issues a sigreturn system callS1APdddA  A @A8 6@T<S1APdddA  A @T<388 static void setup_frame(int sig, struct k_sigaction *ka,SXAPdddA Courier (Tur)A  A A @T)389 sigset_t *set, struct pt_regs * regs)SNAPdddA Courier (Tur)A A @T^390 {SNAPdddA Courier (Tur)A A @Tu391 struct sigframe *frame;SNAPdddA Courier (Tur)A A @Tj392 int err = 0;SNAPdddA Courier (Tur)A A @T]393 SNAPdddA Courier (Tur)A A @TYSNAPdddA Courier (Tur)A A @Tr2Allocate destination space for saving user contextS'APdddA @A8 2TcSXAPdddA Courier (Tur)A  A A @T3394 frame = get_sigframe(ka, regs, sizeof(*frame));SNAPdddA Courier (Tur)A A @T]395 SNAPdddA Courier (Tur)A A @T9396 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))SNAPdddA Courier (Tur)A A @Tq397 goto give_sigsegv;SNAPdddA Courier (Tur)A A @T]398 SNAPdddA Courier (Tur)A A @TcSXAPdddA PA Courier (Tur)A A @T,399 err |= __put_user((current->exec_domainSNAPdddA Courier (Tur)A A @T-400 && current->exec_domain->signal_invmapSNAPdddA Courier (Tur)A A @Tk401 && sig < 32SNAPdddA Courier (Tur)A A @T1402 ? current->exec_domain->signal_invmap[sig]SNAPdddA Courier (Tur)A A @Tg403 : sig),SNAPdddA Courier (Tur)A A @Tm404 &frame->sig);SNAPdddA Courier (Tur)A A @Tf 405 if (err)SNAPdddA Courier (Tur)A A @Tq406 goto give_sigsegv;SNAPdddA Courier (Tur)A A @T]407 SNAPdddA Courier (Tur)A A @TYSNAPdddA Courier (Tur)A A @Ts3Copy user regs from kernel stack back to user stackS'APdddA @A8 3TcSXAPdddA Courier (Tur)A  A A @TS408 err |= setup_sigcontext(&frame->sc, &frame->fpstate, regs, set->sig[0]);SNAPdddA Courier (Tur)A A @Tf 409 if (err)SNAPdddA Courier (Tur)A A @Tq410 goto give_sigsegv;SNAPdddA Courier (Tur)A A @T]411 SNAPdddA Courier (Tur)A A @Ts412 if (_NSIG_WORDS > 1) {SNAPdddA Courier (Tur)A A @T:413 err |= __copy_to_user(frame->extramask, &set->sig[1],SNAPdddA Courier (Tur)A A @Tx414 sizeof(frame->extramask));SNAPdddA Courier (Tur)A A @T^415 }SNAPdddA Courier (Tur)A A @Tf 416 if (err)SNAPdddA Courier (Tur)A A @Tq417 goto give_sigsegv;SNAPdddA Courier (Tur)A A @T]418 SNAPdddA Courier (Tur)A A @TYSNAPdddA Courier (Tur)A A @TXUse of restorer is now deprecated.. normal path is to put sigreturn syscall on the stackS'APdddA @A8 XTcSXAPdddA Courier (Tur)A  A A @TA419 /* Set up to return from userspace. If provided, use a stubSNAPdddA Courier (Tur)A A @Tw420 already in userspace. */SNAPdddA Courier (Tur)A A @T)421 if (ka->sa.sa_flags & SA_RESTORER) {SNAPdddA Courier (Tur)A A @T>422 err |= __put_user(ka->sa.sa_restorer, &frame->pretcode);SNAPdddA Courier (Tur)A A @Tf 423 } else {SNAPdddA Courier (Tur)A A @T:424 err |= __put_user(frame->retcode, &frame->pretcode);SNAPdddA Courier (Tur)A A @T7425 /* This is popl %eax ; movl $,%eax ; int $0x80 */SNAPdddA Courier (Tur)A A @T=426 err |= __put_user(0xb858, (short *)(frame->retcode+0));SNAPdddA Courier (Tur)A A @TL427 err |= __put_user(__NR_sigreturn, (int *)(frame->retcode+2));SNAPdddA Courier (Tur)A A @T=428 err |= __put_user(0x80cd, (short *)(frame->retcode+6));SNAPdddA Courier (Tur)A A @T_429 }SNAPdddA Courier (Tur)A A @T]430 SNAPdddA Courier (Tur)A A @Tf 431 if (err)SNAPdddA Courier (Tur)A A @Tq432 goto give_sigsegv;SNAPdddA Courier (Tur)A A @T]433 SNAPdddA Courier (Tur)A A @TYSNAPdddA Courier (Tur)A A @T5Fixup saved esp and eip to point to frame and handlerS1APdddA PA @A8 5TcSXAPdddA Courier (Tur)A  A A @T-434 /* Set up registers for signal handler */SNAPdddA Courier (Tur)A A @T'435 regs->esp = (unsigned long) frame;SNAPdddA Courier (Tur)A A @T3436 regs->eip = (unsigned long) ka->sa.sa_handler;SNAPdddA Courier (Tur)A A @T]437 SNAPdddA Courier (Tur)A A @TYSNAPdddA Courier (Tur)A A @Ti)Make sure seg regs are back in user mode.S'APdddA @A8 )TcSXAPdddA Courier (Tur)A  A A @Tn438 set_fs(USER_DS);SNAPdddA Courier (Tur)A A @Tt439 regs->xds = __USER_DS;SNAPdddA Courier (Tur)A A @Tt440 regs->xes = __USER_DS;SNAPdddA Courier (Tur)A A @Tt441 regs->xss = __USER_DS;SNAPdddA Courier (Tur)A A @Tt442 regs->xcs = __USER_CS;SNAPdddA Courier (Tur)A A @Tw443 regs->eflags &= ~TF_MASK;SNAPdddA Courier (Tur)A A @T]444 SNAPdddA Courier (Tur)A A @Tk445 #if DEBUG_SIGSNAPdddA Courier (Tur)A A @T7446 printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",SNAPdddA Courier (Tur)A A @TK447 current->comm, current->pid, frame, regs->eip, frame->pretcode);SNAPdddA Courier (Tur)A A @Td 448 #endifSNAPdddA Courier (Tur)A A @T]449 SNAPdddA Courier (Tur)A A @Te 450 return;SNAPdddA Courier (Tur)A A @T]451 SNAPdddA Courier (Tur)A A @Tk452 give_sigsegv:SNAPdddA Courier (Tur)A A @Tq453 if (sig == SIGSEGV)SNAPdddA Courier (Tur)A A @T{"454 ka->sa.sa_handler = SIG_DFL;SNAPdddA Courier (Tur)A A @Tz!455 force_sig(SIGSEGV, current);SNAPdddA Courier (Tur)A A @T^456 }SNAPdddA Courier (Tur)A A @TYSNAPdddA Courier (Tur)A A @TmSbAPdddA PA Courier (Tur)A  A A @TUNo wonder the kernel is getting so large.. there are now three different blessed waysS1APdddA  A @Tc'to allocate space for the saved contextS1APdddA  A @TcSXAPdddA Courier (Tur)A  A A @TYSNAPdddA Courier (Tur)A A @TV365 get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)SNAPdddA Courier (Tur)A A @T^366 {SNAPdddA Courier (Tur)A A @Tp367 unsigned long esp;SNAPdddA Courier (Tur)A A @T]368 SNAPdddA Courier (Tur)A A @T'369 /* Default to using normal stack */SNAPdddA Courier (Tur)A A @Tn370 esp = regs->esp;SNAPdddA Courier (Tur)A A @T]371 SNAPdddA Courier (Tur)A A @T@372 /* This is the X/Open sanctioned signal stack switching. */SNAPdddA Courier (Tur)A A @T(373 if (ka->sa.sa_flags & SA_ONSTACK) {SNAPdddA Courier (Tur)A A @Tz!374 if (sas_ss_flags(esp) == 0)SNAPdddA Courier (Tur)A A @T7375 esp = current->sas_ss_sp + current->sas_ss_size;SNAPdddA Courier (Tur)A A @T`376 }SNAPdddA Courier (Tur)A A @T]377 SNAPdddA Courier (Tur)A A @T4378 /* This is the legacy signal stack switching. */SNAPdddA Courier (Tur)A A @T2379 else if ((regs->xss & 0xffff) != __USER_DS &&SNAPdddA Courier (Tur)A A @T*380 !(ka->sa.sa_flags & SA_RESTORER) &&SNAPdddA Courier (Tur)A A @Tu381 ka->sa.sa_restorer) {SNAPdddA Courier (Tur)A A @T0382 esp = (unsigned long) ka->sa.sa_restorer;SNAPdddA Courier (Tur)A A @T^383 }SNAPdddA Courier (Tur)A A @T]384 SNAPdddA Courier (Tur)A A @T/385 return (void *)((esp - frame_size) & -8ul);SNAPdddA Courier (Tur)A A @T^386 }SNAPdddA Courier (Tur)A A @T]387 SNAPdddA Courier (Tur)A A @TYSNAPdddA Courier (Tur)A A @TFThis just copies the data off the kernel stack and onto the user stackSbAPdddA PA TimesNewRomanA  A A @TYSNAPdddA Courier (Tur)A A @TH319 setup_sigcontext(struct sigcontext *sc, struct _fpstate *fpstate,SNAPdddA Courier (Tur)A A @T-320 struct pt_regs *regs, unsigned long mask)SNAPdddA Courier (Tur)A A @T^321 {SNAPdddA Courier (Tur)A A @To322 int tmp, err = 0;SNAPdddA Courier (Tur)A A @T]323 SNAPdddA Courier (Tur)A A @Tf 324 tmp = 0;SNAPdddA Courier (Tur)A A @T2325 __asm__("movl %%gs,%0" : "=r"(tmp): ""(tmp));SNAPdddA Courier (Tur)A A @T5326 err |= __put_user(tmp, (unsigned int *)&sc->gs);SNAPdddA Courier (Tur)A A @T2327 __asm__("movl %%fs,%0" : "=r"(tmp): ""(tmp));SNAPdddA Courier (Tur)A A @T5328 err |= __put_user(tmp, (unsigned int *)&sc->fs);SNAPdddA Courier (Tur)A A @T]329 SNAPdddA Courier (Tur)A A @T;330 err |= __put_user(regs->xes, (unsigned int *)&sc->es);SNAPdddA Courier (Tur)A A @T;331 err |= __put_user(regs->xds, (unsigned int *)&sc->ds);SNAPdddA Courier (Tur)A A @T,332 err |= __put_user(regs->edi, &sc->edi);SNAPdddA Courier (Tur)A A @T,333 err |= __put_user(regs->esi, &sc->esi);SNAPdddA Courier (Tur)A A @T,334 err |= __put_user(regs->ebp, &sc->ebp);SNAPdddA Courier (Tur)A A @T,335 err |= __put_user(regs->esp, &sc->esp);SNAPdddA Courier (Tur)A A @T,336 err |= __put_user(regs->ebx, &sc->ebx);SNAPdddA Courier (Tur)A A @T,337 err |= __put_user(regs->edx, &sc->edx);SNAPdddA Courier (Tur)A A @T,338 err |= __put_user(regs->ecx, &sc->ecx);SNAPdddA Courier (Tur)A A @T,339 err |= __put_user(regs->eax, &sc->eax);SNAPdddA Courier (Tur)A A @T=340 err |= __put_user(current->thread.trap_no, &sc->trapno);SNAPdddA Courier (Tur)A A @T=341 err |= __put_user(current->thread.error_code, &sc->err);SNAPdddA Courier (Tur)A A @T,342 err |= __put_user(regs->eip, &sc->eip);SNAPdddA Courier (Tur)A A @T;343 err |= __put_user(regs->xcs, (unsigned int *)&sc->cs);SNAPdddA Courier (Tur)A A @T2344 err |= __put_user(regs->eflags, &sc->eflags);SNAPdddA Courier (Tur)A A @T6345 err |= __put_user(regs->esp, &sc->esp_at_signal);SNAPdddA Courier (Tur)A A @T;346 err |= __put_user(regs->xss, (unsigned int *)&sc->ss);SNAPdddA Courier (Tur)A A @T]347 SNAPdddA Courier (Tur)A A @Tw348 tmp = save_i387(fpstate);SNAPdddA Courier (Tur)A A @Tj349 if (tmp < 0)SNAPdddA Courier (Tur)A A @Tg350 err = 1;SNAPdddA Courier (Tur)A A @Tb 351 elseSNAPdddA Courier (Tur)A A @T<352 err |= __put_user(tmp ? fpstate : NULL, &sc->fpstate);SNAPdddA Courier (Tur)A A @T]353 SNAPdddA Courier (Tur)A A @Ty 354 /* non-iBCS2 extensions.. */SNAPdddA Courier (Tur)A A @T+355 err |= __put_user(mask, &sc->oldmask);SNAPdddA Courier (Tur)A A @T6356 err |= __put_user(current->thread.cr2, &sc->cr2);SNAPdddA Courier (Tur)A A @T]357 SNAPdddA Courier (Tur)A A @Ti358 return err;SNAPdddA Courier (Tur)A A @T^359 }SNAPdddA Courier (Tur)A A @T]360 SNAPdddA Courier (Tur)A A @TYSNAPdddA Courier (Tur)A A @T'Return from user level signal handlers:SXAPdddA PA TimesNewRomanA A @TYSNAPdddA TimesNewRomanA A @T2Before signal handler is invoked the setup_frame()S'APdddA @A8 A!8 TimesNewRomanA8 %2T<S1APdddA  A @TGPuts a sys_sigreturn system call in the retcode field of the user stackS1APdddA  A @TEPoints the return address at the top of the frame to that system callS1APdddA  A @T2S'APdddA @Tl166 struct sigframeSNAPdddA Courier (Tur)A A @T^167 {SNAPdddA Courier (Tur)A A @Tn168 char *pretcode;SNAPdddA Courier (Tur)A A @Tg169 int sig;SNAPdddA Courier (Tur)A A @Tt170 struct sigcontext sc;SNAPdddA Courier (Tur)A A @Tw171 struct _fpstate fpstate;SNAPdddA Courier (Tur)A A @T-172 unsigned long extramask[_NSIG_WORDS-1];SNAPdddA Courier (Tur)A A @To173 char retcode[8];SNAPdddA Courier (Tur)A A @T_174 };SNAPdddA Courier (Tur)A A @T2S'APdddA @TIBecause of the upside-down nature of the stack a picture may help clarifyS1APdddA  A @T<S1APdddA  A @T$retcode (sys_sigreturn system call)SXAPdddA Courier (Tur)A  A A @Tl extramaskSXAPdddA Courier (Tur)A  A A @TjfpstateSXAPdddA Courier (Tur)A  A A @TescSXAPdddA Courier (Tur)A  A A @T#sig (parameter to signal handler) SXAPdddA Courier (Tur)A  A A @Tp pretcodeSXAPdddA Courier (Tur)A  A A @TESP->saved EBP <-EBPS'APdddA @A8A8 A!8 Courier (Tur)Td user stackSNAPdddA Courier (Tur)A A @Tr during handler executionSNAPdddA Courier (Tur)A A @T[ |SNAPdddA Courier (Tur)A A @Tx V direction of growth (pushes)SNAPdddA Courier (Tur)A A @TYSNAPdddA Courier (Tur)A A @T]Here is the entry code to a signal handler.. During execution EBP serves as the frame pointerS1APdddA  A @TcSXAPdddA Courier (Tur)A  A A @T) 223 182 0108 55 pushl %ebpSNAPdddA Courier (Tur)A A @T/ 224 183 0109 89E5 movl %esp, %ebpSNAPdddA Courier (Tur)A A @T- 225 184 010b 83EC08 subl $8, %espSNAPdddA Courier (Tur)A A @T2 226 185 010e 8B4508 movl 8(%ebp), %eaxSNAPdddA Courier (Tur)A A @T2 227 186 0111 A3000000 movl %eax, lastsigSNAPdddA Courier (Tur)A A @TYSNAPdddA Courier (Tur)A A @T-Here is the exit code from the signal handlerS'APdddA @A8-A!8- TimesNewRomanTFzThe leave instruction copies EBP to ESP restoring the stack pointer and then pops EBP restoring EBP to that of the caller.S_APdddA TimesNewRomanA A @A@. A8 LA8  A8  A8 $(A8 MzA8 RUA8 `cT8The ret instruction pops EIP leaving ESP pointing at sigSiAPdd:dA TimesNewRomanA  A A @A@. A8 A8 A8 %(A8 58TXThe code in retcode pops EAX putting the signal code back in ax and pointing ESP at sc.SiAPdd:dA TimesNewRomanA  A A @A@. A8  A8 A8 NRT2S'APdddA @T- 244 194 0139 B8000000 movl $0, %eaxSRAPdddACourierA  A A @Tp 245 194 00SRAPdddACourierA  A A @T$ 246 195 013e C9 leaveSRAPdddACourierA  A A @T" 247 196 013f C3 retSRAPdddACourierA  A A @T]SRAPdddACourierA  A A @TYAs just described it is necessary to subtract 8 to recover the sigframe structure pointerSXAPdddA TimesNewRomanA  A A @TcSXAPdddA Courier (Tur)A  A A @T8249 asmlinkage int sys_sigreturn(unsigned long __unused)SNAPdddA Courier (Tur)A A @T^250 {SNAPdddA Courier (Tur)A A @T9251 struct pt_regs *regs = (struct pt_regs *) &__unused;SNAPdddA Courier (Tur)A A @TA252 struct sigframe *frame = (struct sigframe *)(regs->esp - 8);SNAPdddA Courier (Tur)A A @Tk253 sigset_t set;SNAPdddA Courier (Tur)A A @Tf 254 int eax;SNAPdddA Courier (Tur)A A @T\255SNAPdddA Courier (Tur)A A @TYSNAPdddA Courier (Tur)A A @T=Make sure we aren't being dirty tricked by the signal handlerS'APdddA @A8=A8 =A!8= TimesNewRomanTZ SNAPdddA Courier (Tur)A A @T9256 if (verify_area(VERIFY_READ, frame, sizeof(*frame)))SNAPdddA Courier (Tur)A A @Tm257 goto badframe;SNAPdddA Courier (Tur)A A @TYSNAPdddA Courier (Tur)A A @TNCopy the oldmask and extramask which contained signals blocked during handlingSNAPdddA Courier (Tur)A A @A8 NA!8N TimesNewRomanT2S'APdddA @T3258 if (__get_user(set.sig[0], &frame->sc.oldmask)SNAPdddA Courier (Tur)A A @Tr259 || (_NSIG_WORDS > 1SNAPdddA Courier (Tur)A A @T9260 && __copy_from_user(&set.sig[1], &frame->extramask,SNAPdddA Courier (Tur)A A @Tz!261 sizeof(frame->extramask))))SNAPdddA Courier (Tur)A A @Tm262 goto badframe;SNAPdddA Courier (Tur)A A @T\263SNAPdddA Courier (Tur)A A @TYSNAPdddA Courier (Tur)A A @TTMake sure SIGKILL and SIGSTOP are not blocked and reset blocked and pending signals SNAPdddA Courier (Tur)A A @A8 TA!8T TimesNewRomanTZ SNAPdddA Courier (Tur)A A @T&264 sigdelsetmask(&set, ~_BLOCKABLE);SNAPdddA Courier (Tur)A A @T+265 spin_lock_irq(¤t->sigmask_lock);SNAPdddA Courier (Tur)A A @Tu266 current->blocked = set;SNAPdddA Courier (Tur)A A @Ty 267 recalc_sigpending(current);SNAPdddA Courier (Tur)A A @T-268 spin_unlock_irq(¤t->sigmask_lock);SNAPdddA Courier (Tur)A A @T]269 SNAPdddA Courier (Tur)A A @TYSNAPdddA Courier (Tur)A A @T7Copy regs back to the kernel stack from the user frame.SNAPdddA Courier (Tur)A A @A8 7A!87 TimesNewRomanTYSNAPdddA Courier (Tur)A A @T4270 if (restore_sigcontext(regs, &frame->sc, &eax))SNAPdddA Courier (Tur)A A @Tm271 goto badframe;SNAPdddA Courier (Tur)A A @Ti272 return eax;SNAPdddA Courier (Tur)A A @T]273 SNAPdddA Courier (Tur)A A @Tg274 badframe:SNAPdddA Courier (Tur)A A @Tz!275 force_sig(SIGSEGV, current);SNAPdddA Courier (Tur)A A @Tg276 return 0;SNAPdddA Courier (Tur)A A @T_277 } SNAPdddA Courier (Tur)A A @TYSNAPdddA Courier (Tur)A A @JLexmark Optra T614 Laser PrinterLOPT614 PostScript`Tl`Tld,,lp -d lwnlwnLOPT614PageSize:LetterDuplex:NoneDuplexer:FalseInputSlot:AutoSelectMediaType:NoneTray2:FalseTray3:FalseTray4:FalseTray5:FalseMPFeeder:TrueFeeder:FalseImageEnhance:TrueResolution:600dpiSmoothing:False7 UrrV88/d? Щ/=U"&2P  _U"&x0?.B"&B"& B#"& B0"& B="& ER# BJ"& ER# BW"& ER# Bd"& ER# Bq"& E  B~ "& E  B "& E  B "& ER#  B "& E  B "& E B"& E B"& E B"& E B"& E B"& E B"& B "& ER# B"&ER#B"&ER#B"&ER#B"&ER#B"&ER#B"&ER#Br"&ER#BV"&ER#B:"&ER#B"&ER#B"&ER# B"&ER#!B "&ER#"B!"&ER##B""& E $B#"& %B$"& &B%"& ER# 'B&"& ER# (B'"& ER# )B("& ER# *B)"& ER# +B*"& ER# ,B,"& ER# -B-"& ER# .,U6"&("& F @"& >/=U"&2p  ¶U"&x0?%B"&/B"& 0B#"& ER# 1B0"& E 2B="& E 3BJ"& E 4BW"& E 5Bd"& ER# 6Bq"& E 7B~ "&E 8B "& E 9B "& E :B "& E ;B"&ER#<B"&ER#=B"&ER#>Bk"&ER#?@BO"&ER#@AB3"&ER#ABB"&ER#BCB"&ER#CDB"&ER#DEB"&ER#EFB"& ER# FGB"& ER# GHB"& E HIB"& Ep IJB"& E JKB"& E KLB"& E LMB"& E MNB "& E NOB!"& Ep OPB)""& Ep PQB6#"&EoQSBP%"& ER# RTB]&"& ER# SU,U6"&("& F @"& }/=U"&2P  •U"&x0?%B"&TVB"&UWB,"& ER# VXB9"& ER# WYBF"& ER# XZBS"& ER# Y[B`"& E Z\Bm"& E []Bz"& E \^B "& E ]_B "& E ^`B "& E _aB "& ER# `bB "& ER# acB"&bdB"&ceB"& dfB"& ER# egB"&ER#fhB"&ER#giB"&ER#hjB"&ER#ikB"& jlB"& ER# kmB"& ER# lnB"& ER# moB"& ER# npB"&ER#orB"& ER# psB"& ER# qtB "& ER# ruB !"& ER# svB-""& ER# twB:#"& uxBG$"& vyBT%"& ER# wzBa&"& x{,U6"&("& F @"& %/=U"&2p  wU"&x0?B"& y|B "&z}B#"& {~B0"& ER# |B="& ER# }BJ"&ER#~B."&ER#B"&ER#B"& ER# B "& ER# B "&ER#B "&ER#B "&ER#B "&B "& ER# B"& ER# B"&E B"& E B"&E B"& E B"& E B"& E B""& E B/"& E ,U6"&("& F @"& %/=U"&2P  U"&x0?B"& ER# B "& B"& ER# B'"&B "&B"&B"&B"&B"&B"&Bc "&BG "& ER# BT "& ER# Ba "& ER# Bn "& E B{"& E B"& E B"& ER# B"& E B"& E B"& E B"&'E 'B"& E B"&'E 'B$"& E B1"&E BK"& E BX "& ER# ,U6"&("& F @"& F%:/=U"&2p  U"&x0?%B"& ER# B "& ER# B"& E B'"&'E 'BN"& E B["& E Bh"&E B "& E B "& E B "&E B"& E B"& E B"& E B"& E B"& E B"&E B"& ER# B"& ER# B+"& ER# B8"&ER#B"&ER#B"&ER#B"&ER#B"&ER#B"&ER#B"&ER#Bt"&ER#BX "&ER#BB"&/?B}"&E 0@Ba"&E 1ABE"&E 2BB)"&E 3CB "&E 4DB"&E 5E,U6"&("& F @"& i%6/=U"&2p  U"&x0?B"&6FB"&7GB,"& 8HB9"& ER# 9IBF"& ER# :JBS"& E ;KB`"& E <LBm"& E =MBz"& E >NB "& ?OB "&@PBx "&AQB\ "&BRB@ "&CSB$"&DTB"&EUB"&FVB"&GWB"&HXB"&IYB|"&JZB`"&K[BD"&L\B("&M],U6"&("& F @"& R%u/=U"&2P  U"&x0?$B"&N^B"& O_B"& P`B"& ER# QaB "& E RbB"& E ScB%"& E TdB2"& E UeB?"& VfBL "&WgB0 "&XhB "&YiB "&ZjB "&[kB "&\lB"&]mB"&^nBl"&_oBP"&`pB4"&aqB"&brB"&csB"&dtB"&euB"&fvB"&gwBp"&hxBT"&iyB8"&jzB"&k{B"&l|B"&m}B"&n~B"&oB"&pBt "& q,U6"&("& F @"& %Դ/=U"&2p  U"&x0?.B"& rB "& sB"&tB"&uB"&vB"&wB"&xB"&yBr"&zBV"&{B: "&|B "&}B "&~B "&B "&B "&B"&Bv"& B"& ER# B"& ER# B"& ER# B"& ER# B"&B"&B"&Bc"&BG"&B+"&B"&B"&B"&B"&B"&B"&Bg"&BK "&B/!"&B""&B""&B#"&B$"&B%"&B&"&Bk'"&BO("&B3)"&,U6"&("& F @"& Ѝ%/=U"&2P  @U"&x0?(B"&B"&B"&B"&B"&Bt"&BX"&B<"&B "&B"&B "&ER#B "&B "&B "&B "&B"&Bv"&BZ"& Bg"& Bt"&ER#BX"&B<"&B "&B"&B"&B"&B"&B"&Bx"& B"&Bi"&BM"&B1"&B"&B "&B!"&B""&B#"&Bm$"&BQ%"&,U6"&("& F @"& Д%2/=U"&2p  GU"&x0?(B"&B"& ER# B'"&B "&B"&B"&B"&B"&B"&Bc "&BG "&B+ "&B "&B "&B "&B"&B"&B"&Bg"&BK"&B/"&B"&B"&B"&B"&B"& B"& B"& ER# B"& ER# B"&B"&B"&B"&Bg"&BK "&B/!"&B""&B""&B#"&B$"&,U6"&("& F @"& Н%q/=U"&2P  PU"&x0?B"& B "& B"& ER# B'"&B "&B"&B"& B"& B"& B"& Bc "& BG "&B+ "&B "&B "&B "&B"& B"& ER# B"&B"&B"&B"&Be"&BI"&B-"&B"& B"& B"& ,U6"&("& F @"& %İ/=U"&2p  U"&x0?!B"&  B "&   B"& ER# !B'"&ER##BA"& ER# $BN"& ER# %B["&&B?"&'B# "&(B "&)B "&*B "&+B "&,B "&-B{"&.B_"&/BC"&0B'"&1B "&2B"&3B"& 4B"&!5B"&"6B"&#7Bc"&$8BG"&%9B+"&&:B"&';B"&(<B"&)=B"&*>B"&+?B"&,@,U6"&("& F @"& ;%/=U"&2P  U"&x0?0B"&-AB"& .BB"& /CB"& ER# 0DB "& E 1EB"& E 2FB%"& E 3GB2"& 4HB?"&5IB# "&6JB "&7KB "&8LB "&9MB "&:NB "&;OB{"& <PB"&=QBl"&>RBP"&?SB4"&@TB"&AUB"&BVB"&CWB"&DXB"&EYB"&FZBp"&G[BT"&H\B8"&I]B"&J^B3"&K_B"&LaB"&MbB"& NcB "&OdB!"&PeB""&QfB|#"&RgB`$"&ShBD%"&TiB(&"&UjB '"&VkB'"&WlB("&XmB)"&YnB*"&ZoB+"&[pBd,"& \q,U6"&("& F @"& %./=U"&2p  ’U"&x0? B"&]rB"&^tB"&_uB"&`vB"&awBv"&bxB_"& cyBl"&dzBU"&e{B> "&f|B' "&g}B "&h~B "&iB "& jB "&kB"&lB"&mB"&nB"&oB|"&pBe"& qBr"& rB"&sBh"&tBQ"&uB:"&vB#"& wB0"&xB"&yB"&zB"&{B"&|,U6"&("& F @"& C%m/=U"&2P  U"&x0?%B"& }B "&~B"&B"&B"&B"&B"&B"&Bl"&BU"&B> "&B' "&B "&B "&B "&B "&B"&B"&B"&Bo"&BX"&BA"&B*"&B"&B"&B"&B"&B"&B"&B"&Br"&B["&BD"&B-"&B"&B"&B "&,U6"&("& F @"& %/=U"&2p  zU"&x0?&B"&B"&B,"& B9"& BF"& BS"& ER# B`"& ER# Bm"& ER# Bz"& ER# B "& B "& B "& ER# B "& E B "& E B"& E B"& ER# B"& ER# B"& B"& ER# B "& ER# B"& ER# B#"& B0"& B="&B!"&B"&B"&B"&B"&By"&B]"&BA "&B%!"& B2""& B?#"& BL$"& ER# BY%"& ER# Bf&"& ER# ,U6"&("& F @"& %/=U"&2P  ¹U"&x0?-B"& ER# B "&B"&B"&B"&B"&B"&B"&Bl"& By"& B "& B "&B| "&Be "&BN "&B7"&B "&B "&B"&B"&B"& B"& B"& B"&B"&B"&B"&B"& B"& B"& ER# B"& ER# B"& ER# B"& ER# B"& B "&B!"&B""&B#"&B$"&Bw%"&B`&"&BI'"& B2("& B)"& B*"& ,U6"&("& F @"& %*/=U"&2p  2U"&x0?(B"&  B "& B"&B"&B"&B"&B"& B"& B"& B"& B "& B "&B "&B "& B "& B"&B"&B"&B"&B"& Bx"& !Ba"& "BJ"& #B3"& $B"& %B"&&B"&(B"&)B"&*B"&+B"&,B"&-B"& .B "& /B!"& 0B""&1B#"&2B$"&3B%"&4B&"&5,U6"&("& F @"& A%i/=U"&2P  U"&x0?1B"& 6B "& ER# 7B"&8B"& 9B"&!:B"&";B"&#<B"& $=B"& %>B"&ER#&@B "&'AB "&(BB "&)CB "&*DB"&+EBh"&,FBQ"&-GB:"&.HB#"&/IB "&0JB"&1KB"&2LB"&3MB"&4NB"&5OB"&6PBk"&7QBT"&8RB="&9SB&"& :TB3"&;UB"&<VB"&=WB"&>XB "&?YB!"&@ZB""&A[B#"&B\B{$"&C]Bd%"&D^BM&"&E_B6'"&F`B("&GaB)"&HbB)"&IcB*"&JdB+"&KeB,"&LfB-"&Mg,U6"&("& F @"& C%/=U"&2p  U"&x0?%B"& NhB "& OiB"&PjB"&QkB"&RlB"&SmB"&TnB"&UoB"&VpBy"&WqBb "& XrBo "& YsB| "& ZtB "&[uBr "&\vB["&]wBD"&^xB-"&_yB"&`zB"&a{B"&b|B"& c}B"&d~B"&eB"&fB"&gB"&hBk"&iBT"&jB="&kB&"&lB"&mB"&nB"&oB"&pB "&qB!"&r,U6"&("& F @"& k%/=U"&2P  U"&x0?'B"&sB"& tB"&uB"&vB"&wB"&xB"&yB"&zBl"&{BU"&|B> "&}B' "&~B "&B "&B "&B "&B"&B"&B"&Bo"&BX"&BA"&B*"&B"& B "& B-"& B:"&B#"&B "&B"&B"&B"&B"&B"&B"&Bk "&BT!"&B=""&B&#"&,U6"&("& F @"& %&/=U"&2p  ’U"&x0?*B"&B"& B"&B"&B"&B"&B"&B"&Bl"& By"& ER# B "& ER# B "& ER# B "&B "&Br "&B["&BD"&B-"&B"&B"&B"&B"&B"& B"& B"& ER# B"& ER# B"& ER# B"& ER# B"&B"&B"&B"&B"&B"&B~ "&Bg!"& Bt""&ER#B]#"&BF$"&B/%"&B&"&B'"&,U6"&("& F @"& %e/=U"&2P  |U"&x0?+B"&B"&B"&B"&B"&B"&Bv"&B_"&BH"&B1"&B "&B "& B "&ER#B "&B "&B"&B"&B"&Bo"&BX"&BA"&B*"&B"&B"&B"&B"& B"&ER#B"&B"&B"&B"&Bh"&BQ"&B:"&B# "&B !"&B""&B#"&B$"&B%"&B&"&Bk'"& BT("& ,U6"&("& F @"& б%/=U"&2p  dU"&x0?B"&  B "&ER# B"& B"&B"&B"&B"&B"& B"&ER#By"&Bb "&BK "&B4 "&B "&B "&B "&B"&B"&B"&B|"&Be"& BN"&!B7"&"B "&#B "&$B"&%B"& &B"& 'B"& (,U6"&("& F @"& Ъ%/=U"&2P  ]U"&x0?B"& )B"&  *B"& +B"&ER#,B"&-B"&/B"&0B"&1By"&2Bb "&3BK "&4B4 "&5B "&6B "&7B "&8B"&9B"&:B"&;B"&<B|"&=Be"& >BN"&!?B7"&"@B "&#AB "&$BB"&%CB"&&DB"&'EB"&(F,U6"&("& F @"& %"/=U"&2p  –U"&x0?-B"& )GB "&*HB"&+JB"&,KB"&-LB"&.MB"&/NBl"&0OBU"&1PB> "&2QB' "&3RB "&4SB "&5TB "&6UB "&7VB"&8WB"&9XB"&:YBo"&;ZBX"&<[BA"&=\B*"&>]B"&?^B"&@_B"&A`B"&BaB"&CbB"&DcB"&EdBr"&FeB["&GfBD"&HgB-"&IhB"&JiB"&KjB "&LkB!"&MlB""&NmB#"&OnB$"&PoBu%"&QpB^&"&RqBG'"&SrB0("&TsB)"&Ut,U6"&("& F @"& п%a/=U"&2P  rU"&x0?1B"&VuB"&WvB,"& ER# XwB9"& E YxBF"& E ZyBS"& E [zB`"& \{Bm"&]|BV"&^}B? "&_~B( "&`B "&aB "&bB "&cB "&dB"&eB"& fB"& gB"& ER# hB"&E iB"&E jB"&E kB"&E lBi"&E mBR"&ER#nB;"&ER#oB$"&ER#pB "&ER#qB"&ER#rB"&ER#sB"&tB"& uB"&ER#vB"&wB "&xBy!"&yBb""&zBK#"&{B4$"&|B%"& }B*&"&Ej#~BD("& E@# BQ)"& E@# B^*"& Bk+"&BO,"&B3-"&B."&B."&,U6"&("& F @"& %/=U"&2p  ‚U"&x0?,B"& B "&B"&B"&B"&B"&B"&B"&Bl"&BU"&B> "& BK "&B4 "&B "&B "&B "& B"& B "&B"&B"&B"&B"&B"&B"&Bh"& Bu"&B^"&BG"&B0"&B"&B"&B"&B"&B"& B"&B "&B!"&B""&Bn#"&BW$"&B@%"&B)&"&B'"&B'"&,U6"&("& F @"& lZRoot Entry ®`VCompObj<Ole persist elements" SfxDocumentInfo uStarBASIC BasicManager2 4SfxWindowsCSwNumRulesUSfxStyleSheetsStandard*jSummaryInformation( ,0SwPageStyleSheets$ 1StarWriterDocument&