*/
static struct lsm_blob_sizes blob_sizes = {
#ifdef CONFIG_SECURITY_STACKING
- .lbs_task = SECURITY_NAME_MAX + 2,
+ .lbs_task = SECURITY_NAME_MAX + 6,
#endif
};
#else
CONFIG_DEFAULT_SECURITY;
#endif
+static __initdata char chosen_display_lsm[SECURITY_NAME_MAX + 1]
+#ifdef CONFIG_SECURITY_STACKING
+ = CONFIG_SECURITY_DEFAULT_DISPLAY_NAME
+#endif
+;
+static char default_display_lsm[SECURITY_NAME_MAX + 1];
static void __init do_security_initcalls(void)
{
}
__setup("security=", choose_lsm);
+static int __init choose_display_lsm(char *str)
+{
+ strncpy(chosen_display_lsm, str, SECURITY_NAME_MAX);
+ pr_info("LSM: command line set default display lsm %s'\n",
+ chosen_display_lsm);
+ return 1;
+}
+__setup("security.display=", choose_display_lsm);
+
static bool match_last_lsm(const char *list, const char *lsm)
{
const char *last;
/*
* Module defined on the command line security=XXXX
*/
- if (strcmp(chosen_lsms, MODULE_STACK))
- return cmp_lsms(lsm);
-
+ if (strcmp(chosen_lsms, MODULE_STACK)) {
+ if (cmp_lsms(lsm)) {
+ /* set to first LSM registered and then override */
+ if (!*default_display_lsm)
+ strcpy(default_display_lsm, lsm);
+ else if (*chosen_display_lsm && !strcmp(chosen_display_lsm, lsm)) {
+ strcpy(default_display_lsm, lsm);
+ pr_info("LSM: default display lsm '%s'\n", default_display_lsm);
+ }
+ return true;
+ }
+ return false;
+ }
/*
* Module configured as stacked.
*/
+ if (stacked && !*default_display_lsm)
+ strcpy(default_display_lsm, lsm);
+ else if (stacked && *chosen_display_lsm && !strcmp(chosen_display_lsm, lsm)) {
+ strcpy(default_display_lsm, lsm);
+ pr_info("LSM: default display lsm '%s'\n", default_display_lsm);
+ }
+
return stacked;
#else
- if (strcmp(lsm, chosen_lsms) == 0)
+ if (strcmp(lsm, chosen_lsms) == 0) {
+ strcpy(default_display_lsm, lsm);
return true;
+ }
return false;
#endif
}
#ifdef CONFIG_SECURITY_STACKING
if (current->security)
strcpy(task->security, lsm_of_task(current));
+ else
+ strcpy(task->security, default_display_lsm);
#endif
return 0;
}
static char *nolsm = "-default";
#define NOLSMLEN 9
+static bool is_registered_lsm(const char *str, size_t size)
+{
+ struct security_hook_list *hp;
+
+ list_for_each_entry(hp, &security_hook_heads.getprocattr, list) {
+ if (size == strlen(hp->lsm) && !strncmp(str, hp->lsm, size))
+ return true;
+ }
+
+ return false;
+}
+
+static bool set_lsm_of_current(const char *str, size_t size)
+{
+ char *lsm = lsm_of_task(current);
+
+ if (is_registered_lsm(str, size)) {
+ strncpy(lsm, str, size);
+ lsm[size] = '\0';
+ } else if (size == NOLSMLEN && !strncmp(str, nolsm, size)) {
+ lsm[0] = '\0';
+ } else {
+ return false;
+ }
+ return true;
+}
+
static int lsm_task_prctl(int option, unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5)
{
if (copy_from_user(buffer, optval, len))
return -EFAULT;
buffer[len] = '\0';
- /*
- * Trust the caller to know what lsm name(s) are available.
- */
- if (!strncmp(buffer, nolsm, NOLSMLEN))
- lsm[0] = '\0';
- else
- strcpy(lsm, buffer);
+ /* verify the requested LSM is registered */
+ if (!set_lsm_of_current(buffer, len))
+ return -ENOENT;
break;
default:
return -ENOSYS;
if (rc > 0)
return strlen(*value);
return rc;
+ } else if (strcmp(name, "display_lsm") == 0) {
+ *value = kstrdup(current->security, GFP_KERNEL);
+ if (*value == NULL)
+ return -ENOMEM;
+ return strlen(*value);
}
list_for_each_entry(hp, &security_hook_heads.getprocattr, list) {
char *temp;
char *cp;
+ if (!size)
+ return -EINVAL;
+
/*
* If lsm is NULL look at all the modules to find one
* that processes name. If lsm is not NULL only look at
if (rc >= 0)
return size;
return rc;
+ } else if (strcmp(name, "display_lsm") == 0) {
+#ifdef CONFIG_SECURITY_STACKING
+ if (set_lsm_of_current(value, size))
+ return size;
+#endif
+ return -EINVAL;
}
list_for_each_entry(hp, &security_hook_heads.setprocattr, list) {