19
19
20
20
#include "kexec_internal.h"
21
21
22
- static int copy_user_segment_list (struct kimage * image ,
23
- unsigned long nr_segments ,
24
- struct kexec_segment __user * segments )
25
- {
26
- int ret ;
27
- size_t segment_bytes ;
28
-
29
- /* Read in the segments */
30
- image -> nr_segments = nr_segments ;
31
- segment_bytes = nr_segments * sizeof (* segments );
32
- ret = copy_from_user (image -> segment , segments , segment_bytes );
33
- if (ret )
34
- ret = - EFAULT ;
35
-
36
- return ret ;
37
- }
38
-
39
22
static int kimage_alloc_init (struct kimage * * rimage , unsigned long entry ,
40
23
unsigned long nr_segments ,
41
- struct kexec_segment __user * segments ,
24
+ struct kexec_segment * segments ,
42
25
unsigned long flags )
43
26
{
44
27
int ret ;
@@ -58,10 +41,8 @@ static int kimage_alloc_init(struct kimage **rimage, unsigned long entry,
58
41
return - ENOMEM ;
59
42
60
43
image -> start = entry ;
61
-
62
- ret = copy_user_segment_list (image , nr_segments , segments );
63
- if (ret )
64
- goto out_free_image ;
44
+ image -> nr_segments = nr_segments ;
45
+ memcpy (image -> segment , segments , nr_segments * sizeof (* segments ));
65
46
66
47
if (kexec_on_panic ) {
67
48
/* Enable special crash kernel control page alloc policy. */
@@ -104,7 +85,7 @@ static int kimage_alloc_init(struct kimage **rimage, unsigned long entry,
104
85
}
105
86
106
87
static int do_kexec_load (unsigned long entry , unsigned long nr_segments ,
107
- struct kexec_segment __user * segments , unsigned long flags )
88
+ struct kexec_segment * segments , unsigned long flags )
108
89
{
109
90
struct kimage * * dest_image , * image ;
110
91
unsigned long i ;
@@ -250,7 +231,8 @@ static inline int kexec_load_check(unsigned long nr_segments,
250
231
SYSCALL_DEFINE4 (kexec_load , unsigned long , entry , unsigned long , nr_segments ,
251
232
struct kexec_segment __user * , segments , unsigned long , flags )
252
233
{
253
- int result ;
234
+ struct kexec_segment * ksegments ;
235
+ unsigned long result ;
254
236
255
237
result = kexec_load_check (nr_segments , flags );
256
238
if (result )
@@ -261,7 +243,12 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments,
261
243
((flags & KEXEC_ARCH_MASK ) != KEXEC_ARCH_DEFAULT ))
262
244
return - EINVAL ;
263
245
264
- result = do_kexec_load (entry , nr_segments , segments , flags );
246
+ ksegments = memdup_user (segments , nr_segments * sizeof (ksegments [0 ]));
247
+ if (IS_ERR (ksegments ))
248
+ return PTR_ERR (ksegments );
249
+
250
+ result = do_kexec_load (entry , nr_segments , ksegments , flags );
251
+ kfree (ksegments );
265
252
266
253
return result ;
267
254
}
@@ -273,7 +260,7 @@ COMPAT_SYSCALL_DEFINE4(kexec_load, compat_ulong_t, entry,
273
260
compat_ulong_t , flags )
274
261
{
275
262
struct compat_kexec_segment in ;
276
- struct kexec_segment out , __user * ksegments ;
263
+ struct kexec_segment * ksegments ;
277
264
unsigned long i , result ;
278
265
279
266
result = kexec_load_check (nr_segments , flags );
@@ -286,24 +273,26 @@ COMPAT_SYSCALL_DEFINE4(kexec_load, compat_ulong_t, entry,
286
273
if ((flags & KEXEC_ARCH_MASK ) == KEXEC_ARCH_DEFAULT )
287
274
return - EINVAL ;
288
275
289
- ksegments = compat_alloc_user_space (nr_segments * sizeof (out ));
276
+ ksegments = kmalloc_array (nr_segments , sizeof (ksegments [0 ]),
277
+ GFP_KERNEL );
278
+ if (!ksegments )
279
+ return - ENOMEM ;
280
+
290
281
for (i = 0 ; i < nr_segments ; i ++ ) {
291
282
result = copy_from_user (& in , & segments [i ], sizeof (in ));
292
283
if (result )
293
- return - EFAULT ;
284
+ goto fail ;
294
285
295
- out .buf = compat_ptr (in .buf );
296
- out .bufsz = in .bufsz ;
297
- out .mem = in .mem ;
298
- out .memsz = in .memsz ;
299
-
300
- result = copy_to_user (& ksegments [i ], & out , sizeof (out ));
301
- if (result )
302
- return - EFAULT ;
286
+ ksegments [i ].buf = compat_ptr (in .buf );
287
+ ksegments [i ].bufsz = in .bufsz ;
288
+ ksegments [i ].mem = in .mem ;
289
+ ksegments [i ].memsz = in .memsz ;
303
290
}
304
291
305
292
result = do_kexec_load (entry , nr_segments , ksegments , flags );
306
293
294
+ fail :
295
+ kfree (ksegments );
307
296
return result ;
308
297
}
309
298
#endif
0 commit comments