diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/Kconfig | 2 | ||||
-rw-r--r-- | security/security.c | 19 |
2 files changed, 20 insertions, 1 deletions
diff --git a/security/Kconfig b/security/Kconfig index 93027fdf47d1..bdcbb92927ab 100644 --- a/security/Kconfig +++ b/security/Kconfig @@ -139,7 +139,7 @@ config HARDENED_USERCOPY copying memory to/from the kernel (via copy_to_user() and copy_from_user() functions) by rejecting memory ranges that are larger than the specified heap object, span multiple - separately allocates pages, are not on the process stack, + separately allocated pages, are not on the process stack, or are part of the kernel text. This kills entire classes of heap overflow exploits and similar kernel memory exposures. diff --git a/security/security.c b/security/security.c index b9fea3999cf8..38316bb28b16 100644 --- a/security/security.c +++ b/security/security.c @@ -25,6 +25,7 @@ #include <linux/mount.h> #include <linux/personality.h> #include <linux/backing-dev.h> +#include <linux/string.h> #include <net/flow.h> #define MAX_LSM_EVM_XATTR 2 @@ -86,6 +87,21 @@ static int __init choose_lsm(char *str) } __setup("security=", choose_lsm); +static bool match_last_lsm(const char *list, const char *lsm) +{ + const char *last; + + if (WARN_ON(!list || !lsm)) + return false; + last = strrchr(list, ','); + if (last) + /* Pass the comma, strcmp() will check for '\0' */ + last++; + else + last = list; + return !strcmp(last, lsm); +} + static int lsm_append(char *new, char **result) { char *cp; @@ -93,6 +109,9 @@ static int lsm_append(char *new, char **result) if (*result == NULL) { *result = kstrdup(new, GFP_KERNEL); } else { + /* Check if it is the last registered name */ + if (match_last_lsm(*result, new)) + return 0; cp = kasprintf(GFP_KERNEL, "%s,%s", *result, new); if (cp == NULL) return -ENOMEM; |