Skip to content

Commit f431175

Browse files
chleroyrafaeljw
authored andcommitted
PM: hibernate: Don't ignore return from set_memory_ro()
set_memory_ro() and set_memory_rw() can fail, leaving memory unprotected. Take the returned value into account and abort in case of failure. Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu> Reviewed-by: Kees Cook <keescook@chromium.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent 3fec6e5 commit f431175

File tree

4 files changed

+24
-15
lines changed

4 files changed

+24
-15
lines changed

kernel/power/power.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ extern unsigned int snapshot_additional_pages(struct zone *zone);
153153
extern unsigned long snapshot_get_image_size(void);
154154
extern int snapshot_read_next(struct snapshot_handle *handle);
155155
extern int snapshot_write_next(struct snapshot_handle *handle);
156-
extern void snapshot_write_finalize(struct snapshot_handle *handle);
156+
int snapshot_write_finalize(struct snapshot_handle *handle);
157157
extern int snapshot_image_loaded(struct snapshot_handle *handle);
158158

159159
extern bool hibernate_acquire(void);

kernel/power/snapshot.c

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,22 +58,24 @@ static inline void hibernate_restore_protection_end(void)
5858
hibernate_restore_protection_active = false;
5959
}
6060

61-
static inline void hibernate_restore_protect_page(void *page_address)
61+
static inline int __must_check hibernate_restore_protect_page(void *page_address)
6262
{
6363
if (hibernate_restore_protection_active)
64-
set_memory_ro((unsigned long)page_address, 1);
64+
return set_memory_ro((unsigned long)page_address, 1);
65+
return 0;
6566
}
6667

67-
static inline void hibernate_restore_unprotect_page(void *page_address)
68+
static inline int hibernate_restore_unprotect_page(void *page_address)
6869
{
6970
if (hibernate_restore_protection_active)
70-
set_memory_rw((unsigned long)page_address, 1);
71+
return set_memory_rw((unsigned long)page_address, 1);
72+
return 0;
7173
}
7274
#else
7375
static inline void hibernate_restore_protection_begin(void) {}
7476
static inline void hibernate_restore_protection_end(void) {}
75-
static inline void hibernate_restore_protect_page(void *page_address) {}
76-
static inline void hibernate_restore_unprotect_page(void *page_address) {}
77+
static inline int __must_check hibernate_restore_protect_page(void *page_address) {return 0; }
78+
static inline int hibernate_restore_unprotect_page(void *page_address) {return 0; }
7779
#endif /* CONFIG_STRICT_KERNEL_RWX && CONFIG_ARCH_HAS_SET_MEMORY */
7880

7981

@@ -2832,7 +2834,9 @@ int snapshot_write_next(struct snapshot_handle *handle)
28322834
}
28332835
} else {
28342836
copy_last_highmem_page();
2835-
hibernate_restore_protect_page(handle->buffer);
2837+
error = hibernate_restore_protect_page(handle->buffer);
2838+
if (error)
2839+
return error;
28362840
handle->buffer = get_buffer(&orig_bm, &ca);
28372841
if (IS_ERR(handle->buffer))
28382842
return PTR_ERR(handle->buffer);
@@ -2858,15 +2862,18 @@ int snapshot_write_next(struct snapshot_handle *handle)
28582862
* stored in highmem. Additionally, it recycles bitmap memory that's not
28592863
* necessary any more.
28602864
*/
2861-
void snapshot_write_finalize(struct snapshot_handle *handle)
2865+
int snapshot_write_finalize(struct snapshot_handle *handle)
28622866
{
2867+
int error;
2868+
28632869
copy_last_highmem_page();
2864-
hibernate_restore_protect_page(handle->buffer);
2870+
error = hibernate_restore_protect_page(handle->buffer);
28652871
/* Do that only if we have loaded the image entirely */
28662872
if (handle->cur > 1 && handle->cur > nr_meta_pages + nr_copy_pages + nr_zero_pages) {
28672873
memory_bm_recycle(&orig_bm);
28682874
free_highmem_data();
28692875
}
2876+
return error;
28702877
}
28712878

28722879
int snapshot_image_loaded(struct snapshot_handle *handle)

kernel/power/swap.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,8 +1134,8 @@ static int load_image(struct swap_map_handle *handle,
11341134
ret = err2;
11351135
if (!ret) {
11361136
pr_info("Image loading done\n");
1137-
snapshot_write_finalize(snapshot);
1138-
if (!snapshot_image_loaded(snapshot))
1137+
ret = snapshot_write_finalize(snapshot);
1138+
if (!ret && !snapshot_image_loaded(snapshot))
11391139
ret = -ENODATA;
11401140
}
11411141
swsusp_show_speed(start, stop, nr_to_read, "Read");
@@ -1486,8 +1486,8 @@ static int load_compressed_image(struct swap_map_handle *handle,
14861486
stop = ktime_get();
14871487
if (!ret) {
14881488
pr_info("Image loading done\n");
1489-
snapshot_write_finalize(snapshot);
1490-
if (!snapshot_image_loaded(snapshot))
1489+
ret = snapshot_write_finalize(snapshot);
1490+
if (!ret && !snapshot_image_loaded(snapshot))
14911491
ret = -ENODATA;
14921492
if (!ret) {
14931493
if (swsusp_header->flags & SF_CRC32_MODE) {

kernel/power/user.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,9 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
317317
break;
318318

319319
case SNAPSHOT_ATOMIC_RESTORE:
320-
snapshot_write_finalize(&data->handle);
320+
error = snapshot_write_finalize(&data->handle);
321+
if (error)
322+
break;
321323
if (data->mode != O_WRONLY || !data->frozen ||
322324
!snapshot_image_loaded(&data->handle)) {
323325
error = -EPERM;

0 commit comments

Comments
 (0)