@@ -60,11 +60,13 @@ static inline int copy_with_mvcos(void)
6060#endif
6161
6262static inline unsigned long copy_from_user_mvcos (void * x , const void __user * ptr ,
63- unsigned long size )
63+ unsigned long size , unsigned long key )
6464{
6565 unsigned long tmp1 , tmp2 ;
6666 union oac spec = {
67+ .oac2 .key = key ,
6768 .oac2 .as = PSW_BITS_AS_SECONDARY ,
69+ .oac2 .k = 1 ,
6870 .oac2 .a = 1 ,
6971 };
7072
@@ -95,19 +97,19 @@ static inline unsigned long copy_from_user_mvcos(void *x, const void __user *ptr
9597}
9698
9799static inline unsigned long copy_from_user_mvcp (void * x , const void __user * ptr ,
98- unsigned long size )
100+ unsigned long size , unsigned long key )
99101{
100102 unsigned long tmp1 , tmp2 ;
101103
102104 tmp1 = -256UL ;
103105 asm volatile (
104106 " sacf 0\n"
105- "0: mvcp 0(%0,%2),0(%1),%3 \n"
107+ "0: mvcp 0(%0,%2),0(%1),%[key] \n"
106108 "7: jz 5f\n"
107109 "1: algr %0,%3\n"
108110 " la %1,256(%1)\n"
109111 " la %2,256(%2)\n"
110- "2: mvcp 0(%0,%2),0(%1),%3 \n"
112+ "2: mvcp 0(%0,%2),0(%1),%[key] \n"
111113 "8: jnz 1b\n"
112114 " j 5f\n"
113115 "3: la %4,255(%1)\n" /* %4 = ptr + 255 */
@@ -116,32 +118,57 @@ static inline unsigned long copy_from_user_mvcp(void *x, const void __user *ptr,
116118 " slgr %4,%1\n"
117119 " clgr %0,%4\n" /* copy crosses next page boundary? */
118120 " jnh 6f\n"
119- "4: mvcp 0(%4,%2),0(%1),%3 \n"
121+ "4: mvcp 0(%4,%2),0(%1),%[key] \n"
120122 "9: slgr %0,%4\n"
121123 " j 6f\n"
122124 "5: slgr %0,%0\n"
123125 "6: sacf 768\n"
124126 EX_TABLE (0b ,3b ) EX_TABLE (2b ,3b ) EX_TABLE (4b ,6b )
125127 EX_TABLE (7b ,3b ) EX_TABLE (8b ,3b ) EX_TABLE (9b ,6b )
126128 : "+a" (size ), "+a" (ptr ), "+a" (x ), "+a" (tmp1 ), "=a" (tmp2 )
127- : : "cc" , "memory" );
129+ : [key ] "d" (key << 4 )
130+ : "cc" , "memory" );
128131 return size ;
129132}
130133
131- unsigned long raw_copy_from_user (void * to , const void __user * from , unsigned long n )
134+ static unsigned long raw_copy_from_user_key (void * to , const void __user * from ,
135+ unsigned long n , unsigned long key )
132136{
133137 if (copy_with_mvcos ())
134- return copy_from_user_mvcos (to , from , n );
135- return copy_from_user_mvcp (to , from , n );
138+ return copy_from_user_mvcos (to , from , n , key );
139+ return copy_from_user_mvcp (to , from , n , key );
140+ }
141+
142+ unsigned long raw_copy_from_user (void * to , const void __user * from , unsigned long n )
143+ {
144+ return raw_copy_from_user_key (to , from , n , 0 );
136145}
137146EXPORT_SYMBOL (raw_copy_from_user );
138147
148+ unsigned long _copy_from_user_key (void * to , const void __user * from ,
149+ unsigned long n , unsigned long key )
150+ {
151+ unsigned long res = n ;
152+
153+ might_fault ();
154+ if (!should_fail_usercopy ()) {
155+ instrument_copy_from_user (to , from , n );
156+ res = raw_copy_from_user_key (to , from , n , key );
157+ }
158+ if (unlikely (res ))
159+ memset (to + (n - res ), 0 , res );
160+ return res ;
161+ }
162+ EXPORT_SYMBOL (_copy_from_user_key );
163+
139164static inline unsigned long copy_to_user_mvcos (void __user * ptr , const void * x ,
140- unsigned long size )
165+ unsigned long size , unsigned long key )
141166{
142167 unsigned long tmp1 , tmp2 ;
143168 union oac spec = {
169+ .oac1 .key = key ,
144170 .oac1 .as = PSW_BITS_AS_SECONDARY ,
171+ .oac1 .k = 1 ,
145172 .oac1 .a = 1 ,
146173 };
147174
@@ -172,19 +199,19 @@ static inline unsigned long copy_to_user_mvcos(void __user *ptr, const void *x,
172199}
173200
174201static inline unsigned long copy_to_user_mvcs (void __user * ptr , const void * x ,
175- unsigned long size )
202+ unsigned long size , unsigned long key )
176203{
177204 unsigned long tmp1 , tmp2 ;
178205
179206 tmp1 = -256UL ;
180207 asm volatile (
181208 " sacf 0\n"
182- "0: mvcs 0(%0,%1),0(%2),%3 \n"
209+ "0: mvcs 0(%0,%1),0(%2),%[key] \n"
183210 "7: jz 5f\n"
184211 "1: algr %0,%3\n"
185212 " la %1,256(%1)\n"
186213 " la %2,256(%2)\n"
187- "2: mvcs 0(%0,%1),0(%2),%3 \n"
214+ "2: mvcs 0(%0,%1),0(%2),%[key] \n"
188215 "8: jnz 1b\n"
189216 " j 5f\n"
190217 "3: la %4,255(%1)\n" /* %4 = ptr + 255 */
@@ -193,26 +220,44 @@ static inline unsigned long copy_to_user_mvcs(void __user *ptr, const void *x,
193220 " slgr %4,%1\n"
194221 " clgr %0,%4\n" /* copy crosses next page boundary? */
195222 " jnh 6f\n"
196- "4: mvcs 0(%4,%1),0(%2),%3 \n"
223+ "4: mvcs 0(%4,%1),0(%2),%[key] \n"
197224 "9: slgr %0,%4\n"
198225 " j 6f\n"
199226 "5: slgr %0,%0\n"
200227 "6: sacf 768\n"
201228 EX_TABLE (0b ,3b ) EX_TABLE (2b ,3b ) EX_TABLE (4b ,6b )
202229 EX_TABLE (7b ,3b ) EX_TABLE (8b ,3b ) EX_TABLE (9b ,6b )
203230 : "+a" (size ), "+a" (ptr ), "+a" (x ), "+a" (tmp1 ), "=a" (tmp2 )
204- : : "cc" , "memory" );
231+ : [key ] "d" (key << 4 )
232+ : "cc" , "memory" );
205233 return size ;
206234}
207235
208- unsigned long raw_copy_to_user (void __user * to , const void * from , unsigned long n )
236+ static unsigned long raw_copy_to_user_key (void __user * to , const void * from ,
237+ unsigned long n , unsigned long key )
209238{
210239 if (copy_with_mvcos ())
211- return copy_to_user_mvcos (to , from , n );
212- return copy_to_user_mvcs (to , from , n );
240+ return copy_to_user_mvcos (to , from , n , key );
241+ return copy_to_user_mvcs (to , from , n , key );
242+ }
243+
244+ unsigned long raw_copy_to_user (void __user * to , const void * from , unsigned long n )
245+ {
246+ return raw_copy_to_user_key (to , from , n , 0 );
213247}
214248EXPORT_SYMBOL (raw_copy_to_user );
215249
250+ unsigned long _copy_to_user_key (void __user * to , const void * from ,
251+ unsigned long n , unsigned long key )
252+ {
253+ might_fault ();
254+ if (should_fail_usercopy ())
255+ return n ;
256+ instrument_copy_to_user (to , from , n );
257+ return raw_copy_to_user_key (to , from , n , key );
258+ }
259+ EXPORT_SYMBOL (_copy_to_user_key );
260+
216261static inline unsigned long clear_user_mvcos (void __user * to , unsigned long size )
217262{
218263 unsigned long tmp1 , tmp2 ;
0 commit comments