@@ -60,10 +60,22 @@ struct rt_signal_frame {
6060#define SF_ALIGNEDSZ (((sizeof(struct signal_frame) + 7) & (~7)))
6161#define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7)))
6262
63+ /* Checks if the fp is valid. We always build signal frames which are
64+ * 16-byte aligned, therefore we can always enforce that the restore
65+ * frame has that property as well.
66+ */
67+ static inline bool invalid_frame_pointer (void __user * fp , int fplen )
68+ {
69+ if ((((unsigned long ) fp ) & 15 ) || !__access_ok ((unsigned long )fp , fplen ))
70+ return true;
71+
72+ return false;
73+ }
74+
6375asmlinkage void do_sigreturn (struct pt_regs * regs )
6476{
77+ unsigned long up_psr , pc , npc , ufp ;
6578 struct signal_frame __user * sf ;
66- unsigned long up_psr , pc , npc ;
6779 sigset_t set ;
6880 __siginfo_fpu_t __user * fpu_save ;
6981 __siginfo_rwin_t __user * rwin_save ;
@@ -77,10 +89,13 @@ asmlinkage void do_sigreturn(struct pt_regs *regs)
7789 sf = (struct signal_frame __user * ) regs -> u_regs [UREG_FP ];
7890
7991 /* 1. Make sure we are not getting garbage from the user */
80- if (!access_ok (VERIFY_READ , sf , sizeof (* sf )))
92+ if (!invalid_frame_pointer (sf , sizeof (* sf )))
93+ goto segv_and_exit ;
94+
95+ if (get_user (ufp , & sf -> info .si_regs .u_regs [UREG_FP ]))
8196 goto segv_and_exit ;
8297
83- if ((( unsigned long ) sf ) & 3 )
98+ if (ufp & 0x7 )
8499 goto segv_and_exit ;
85100
86101 err = __get_user (pc , & sf -> info .si_regs .pc );
@@ -127,16 +142,21 @@ asmlinkage void do_sigreturn(struct pt_regs *regs)
127142asmlinkage void do_rt_sigreturn (struct pt_regs * regs )
128143{
129144 struct rt_signal_frame __user * sf ;
130- unsigned int psr , pc , npc ;
145+ unsigned int psr , pc , npc , ufp ;
131146 __siginfo_fpu_t __user * fpu_save ;
132147 __siginfo_rwin_t __user * rwin_save ;
133148 sigset_t set ;
134149 int err ;
135150
136151 synchronize_user_stack ();
137152 sf = (struct rt_signal_frame __user * ) regs -> u_regs [UREG_FP ];
138- if (!access_ok (VERIFY_READ , sf , sizeof (* sf )) ||
139- (((unsigned long ) sf ) & 0x03 ))
153+ if (!invalid_frame_pointer (sf , sizeof (* sf )))
154+ goto segv ;
155+
156+ if (get_user (ufp , & sf -> regs .u_regs [UREG_FP ]))
157+ goto segv ;
158+
159+ if (ufp & 0x7 )
140160 goto segv ;
141161
142162 err = __get_user (pc , & sf -> regs .pc );
@@ -178,15 +198,6 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
178198 force_sig (SIGSEGV , current );
179199}
180200
181- /* Checks if the fp is valid */
182- static inline int invalid_frame_pointer (void __user * fp , int fplen )
183- {
184- if ((((unsigned long ) fp ) & 7 ) || !__access_ok ((unsigned long )fp , fplen ))
185- return 1 ;
186-
187- return 0 ;
188- }
189-
190201static inline void __user * get_sigframe (struct ksignal * ksig , struct pt_regs * regs , unsigned long framesize )
191202{
192203 unsigned long sp = regs -> u_regs [UREG_FP ];
0 commit comments