| From 4e4110382c4070020a3224153092adf35db4c06f Mon Sep 17 00:00:00 2001 |
| From: Cyrill Gorcunov <gorcunov@gmail.com> |
| Date: Mon, 13 May 2019 17:15:40 -0700 |
| Subject: kernel/sys.c: prctl: fix false positive in validate_prctl_map() |
| |
| [ Upstream commit a9e73998f9d705c94a8dca9687633adc0f24a19a ] |
| |
| While validating new map we require the @start_data to be strictly less |
| than @end_data, which is fine for regular applications (this is why this |
| nit didn't trigger for that long). These members are set from executable |
| loaders such as elf handers, still it is pretty valid to have a loadable |
| data section with zero size in file, in such case the start_data is equal |
| to end_data once kernel loader finishes. |
| |
| As a result when we're trying to restore such programs the procedure fails |
| and the kernel returns -EINVAL. From the image dump of a program: |
| |
| | "mm_start_code": "0x400000", |
| | "mm_end_code": "0x8f5fb4", |
| | "mm_start_data": "0xf1bfb0", |
| | "mm_end_data": "0xf1bfb0", |
| |
| Thus we need to change validate_prctl_map from strictly less to less or |
| equal operator use. |
| |
| Link: http://lkml.kernel.org/r/20190408143554.GY1421@uranus.lan |
| Fixes: f606b77f1a9e3 ("prctl: PR_SET_MM -- introduce PR_SET_MM_MAP operation") |
| Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com> |
| Cc: Andrey Vagin <avagin@gmail.com> |
| Cc: Dmitry Safonov <0x7f454c46@gmail.com> |
| Cc: Pavel Emelyanov <xemul@virtuozzo.com> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| kernel/sys.c | 2 +- |
| 1 file changed, 1 insertion(+), 1 deletion(-) |
| |
| diff --git a/kernel/sys.c b/kernel/sys.c |
| index 12df0e5434b8..bdbfe8d37418 100644 |
| --- a/kernel/sys.c |
| +++ b/kernel/sys.c |
| @@ -1924,7 +1924,7 @@ static int validate_prctl_map(struct prctl_mm_map *prctl_map) |
| ((unsigned long)prctl_map->__m1 __op \ |
| (unsigned long)prctl_map->__m2) ? 0 : -EINVAL |
| error = __prctl_check_order(start_code, <, end_code); |
| - error |= __prctl_check_order(start_data, <, end_data); |
| + error |= __prctl_check_order(start_data,<=, end_data); |
| error |= __prctl_check_order(start_brk, <=, brk); |
| error |= __prctl_check_order(arg_start, <=, arg_end); |
| error |= __prctl_check_order(env_start, <=, env_end); |
| -- |
| 2.20.1 |
| |