From da3caa204ca40c32dcb751ebead2a6835b83e8d1 Mon Sep 17 00:00:00 2001 From: Gerald Schaefer Date: Tue, 21 Jun 2005 17:15:18 -0700 Subject: [PATCH] SELinux: memory leak in selinux_sb_copy_data() There is a memory leak during mount when SELinux is active and mount options are specified. Signed-off-by: Gerald Schaefer Acked-by: Stephen Smalley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- security/selinux/hooks.c | 1 + 1 file changed, 1 insertion(+) (limited to 'security/selinux') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index db845cbd5841..87302a49067b 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1945,6 +1945,7 @@ static int selinux_sb_copy_data(struct file_system_type *type, void *orig, void } while (*in_end++); copy_page(in_save, nosec_save); + free_page((unsigned long)nosec_save); out: return rc; } -- cgit v1.2.3 From 6b9921976f0861e04828b3aff66696c1f3fd900d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lorenzo=20Hernandez=20Garc=EDa-Hierro?= Date: Sat, 25 Jun 2005 14:54:34 -0700 Subject: [PATCH] selinux: add executable stack check This patch adds an execstack permission check that controls the ability to make the main process stack executable so that attempts to make the stack executable can still be prevented even if the process is allowed the existing execmem permission in order to e.g. perform runtime code generation. Note that this does not yet address thread stacks. Note also that unlike the execmem check, the execstack check is only applied on mprotect calls, not mmap calls, as the current security_file_mmap hook is not passed the necessary information presently. The original author of the code that makes the distinction of the stack region, is Ingo Molnar, who wrote it within his patch for /proc//maps markers. (http://marc.theaimsgroup.com/?l=linux-kernel&m=110719881508591&w=2) The patches also can be found at: http://pearls.tuxedo-es.org/patches/selinux/policy-execstack.patch http://pearls.tuxedo-es.org/patches/selinux/kernel-execstack.patch policy-execstack.patch is the patch that needs to be applied to the policy in order to support the execstack permission and exclude it from general_domain_access within macros/core_macros.te. kernel-execstack.patch adds such permission to the SELinux code within the kernel and adds the proper permission check to the selinux_file_mprotect() hook. Signed-off-by: Lorenzo Hernandez Garcia-Hierro Acked-by: James Morris Acked-by: Stephen Smalley Cc: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- security/selinux/hooks.c | 10 ++++++++++ security/selinux/include/av_perm_to_string.h | 1 + security/selinux/include/av_permissions.h | 1 + 3 files changed, 12 insertions(+) (limited to 'security/selinux') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 87302a49067b..ad725213f568 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2488,6 +2488,16 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, if (rc) return rc; } + if (!vma->vm_file && (prot & PROT_EXEC) && + vma->vm_start <= vma->vm_mm->start_stack && + vma->vm_end >= vma->vm_mm->start_stack) { + /* Attempt to make the process stack executable. + * This has an additional execstack check. + */ + rc = task_has_perm(current, current, PROCESS__EXECSTACK); + if (rc) + return rc; + } #endif return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED); diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h index 8928bb4d3c53..e81f0226c37d 100644 --- a/security/selinux/include/av_perm_to_string.h +++ b/security/selinux/include/av_perm_to_string.h @@ -70,6 +70,7 @@ S_(SECCLASS_PROCESS, PROCESS__DYNTRANSITION, "dyntransition") S_(SECCLASS_PROCESS, PROCESS__SETCURRENT, "setcurrent") S_(SECCLASS_PROCESS, PROCESS__EXECMEM, "execmem") + S_(SECCLASS_PROCESS, PROCESS__EXECSTACK, "execstack") S_(SECCLASS_MSGQ, MSGQ__ENQUEUE, "enqueue") S_(SECCLASS_MSG, MSG__SEND, "send") S_(SECCLASS_MSG, MSG__RECEIVE, "receive") diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h index bdfce4ca8f8e..38ce18b33284 100644 --- a/security/selinux/include/av_permissions.h +++ b/security/selinux/include/av_permissions.h @@ -465,6 +465,7 @@ #define PROCESS__DYNTRANSITION 0x00800000UL #define PROCESS__SETCURRENT 0x01000000UL #define PROCESS__EXECMEM 0x02000000UL +#define PROCESS__EXECSTACK 0x04000000UL #define IPC__CREATE 0x00000001UL #define IPC__DESTROY 0x00000002UL -- cgit v1.2.3 From 09ffd94fb15d85fbf9eebb8180f50264b264d6fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lorenzo=20Hern=E1ndez=20Garc=EDa-Hierro?= Date: Sat, 25 Jun 2005 14:54:35 -0700 Subject: [PATCH] selinux: add executable heap check This patch,based on sample code by Roland McGrath, adds an execheap permission check that controls the ability to make the heap executable so that this can be prevented in almost all cases (the X server is presently an exception, but this will hopefully be resolved in the future) so that even programs with execmem permission will need to have the anonymous memory mapped in order to make it executable. The only reason that we use a permission check for such restriction (vs. making it unconditional) is that the X module loader presently needs it; it could possibly be made unconditional in the future when X is changed. The policy patch for the execheap permission is available at: http://pearls.tuxedo-es.org/patches/selinux/policy-execheap.patch Signed-off-by: Lorenzo Hernandez Garcia-Hierro Acked-by: James Morris Acked-by: Stephen Smalley Cc: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- security/selinux/hooks.c | 11 +++++++++++ security/selinux/include/av_perm_to_string.h | 1 + security/selinux/include/av_permissions.h | 1 + 3 files changed, 13 insertions(+) (limited to 'security/selinux') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index ad725213f568..932eef18db33 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2477,6 +2477,17 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, prot = reqprot; #ifndef CONFIG_PPC32 + if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXECUTABLE) && + (vma->vm_start >= vma->vm_mm->start_brk && + vma->vm_end <= vma->vm_mm->brk)) { + /* + * We are making an executable mapping in the brk region. + * This has an additional execheap check. + */ + rc = task_has_perm(current, current, PROCESS__EXECHEAP); + if (rc) + return rc; + } if (vma->vm_file != NULL && vma->anon_vma != NULL && (prot & PROT_EXEC)) { /* * We are making executable a file mapping that has diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h index e81f0226c37d..1deb59e1b762 100644 --- a/security/selinux/include/av_perm_to_string.h +++ b/security/selinux/include/av_perm_to_string.h @@ -71,6 +71,7 @@ S_(SECCLASS_PROCESS, PROCESS__SETCURRENT, "setcurrent") S_(SECCLASS_PROCESS, PROCESS__EXECMEM, "execmem") S_(SECCLASS_PROCESS, PROCESS__EXECSTACK, "execstack") + S_(SECCLASS_PROCESS, PROCESS__EXECHEAP, "execheap") S_(SECCLASS_MSGQ, MSGQ__ENQUEUE, "enqueue") S_(SECCLASS_MSG, MSG__SEND, "send") S_(SECCLASS_MSG, MSG__RECEIVE, "receive") diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h index 38ce18b33284..a78b5d59c9fc 100644 --- a/security/selinux/include/av_permissions.h +++ b/security/selinux/include/av_permissions.h @@ -466,6 +466,7 @@ #define PROCESS__SETCURRENT 0x01000000UL #define PROCESS__EXECMEM 0x02000000UL #define PROCESS__EXECSTACK 0x04000000UL +#define PROCESS__EXECHEAP 0x08000000UL #define IPC__CREATE 0x00000001UL #define IPC__DESTROY 0x00000002UL -- cgit v1.2.3 From 9a5f04bf798254390f89445ecf0b6f4c70ddc1f8 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sat, 25 Jun 2005 14:58:51 -0700 Subject: [PATCH] selinux: kfree cleanup kfree(NULL) is legal. Signed-off-by: Jesper Juhl Acked-by: Stephen Smalley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- security/selinux/hooks.c | 3 +-- security/selinux/selinuxfs.c | 9 +++------ security/selinux/ss/conditional.c | 9 +++------ security/selinux/ss/policydb.c | 15 +++++---------- security/selinux/ss/services.c | 6 ++---- 5 files changed, 14 insertions(+), 28 deletions(-) (limited to 'security/selinux') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 932eef18db33..17a1189f1ff8 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1658,9 +1658,8 @@ static int selinux_bprm_secureexec (struct linux_binprm *bprm) static void selinux_bprm_free_security(struct linux_binprm *bprm) { - struct bprm_security_struct *bsec = bprm->security; + kfree(bprm->security); bprm->security = NULL; - kfree(bsec); } extern struct vfsmount *selinuxfs_mount; diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 07221568b505..8eb140dd2e4b 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -951,8 +951,7 @@ static int sel_make_bools(void) u32 sid; /* remove any existing files */ - if (bool_pending_values) - kfree(bool_pending_values); + kfree(bool_pending_values); sel_remove_bools(dir); @@ -997,10 +996,8 @@ static int sel_make_bools(void) out: free_page((unsigned long)page); if (names) { - for (i = 0; i < num; i++) { - if (names[i]) - kfree(names[i]); - } + for (i = 0; i < num; i++) + kfree(names[i]); kfree(names); } return ret; diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c index b53441184aca..e2057f5a411a 100644 --- a/security/selinux/ss/conditional.c +++ b/security/selinux/ss/conditional.c @@ -166,16 +166,14 @@ static void cond_list_destroy(struct cond_node *list) void cond_policydb_destroy(struct policydb *p) { - if (p->bool_val_to_struct != NULL) - kfree(p->bool_val_to_struct); + kfree(p->bool_val_to_struct); avtab_destroy(&p->te_cond_avtab); cond_list_destroy(p->cond_list); } int cond_init_bool_indexes(struct policydb *p) { - if (p->bool_val_to_struct) - kfree(p->bool_val_to_struct); + kfree(p->bool_val_to_struct); p->bool_val_to_struct = (struct cond_bool_datum**) kmalloc(p->p_bools.nprim * sizeof(struct cond_bool_datum*), GFP_KERNEL); if (!p->bool_val_to_struct) @@ -185,8 +183,7 @@ int cond_init_bool_indexes(struct policydb *p) int cond_destroy_bool(void *key, void *datum, void *p) { - if (key) - kfree(key); + kfree(key); kfree(datum); return 0; } diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 14190efbf333..785c33cf4864 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -590,17 +590,12 @@ void policydb_destroy(struct policydb *p) hashtab_destroy(p->symtab[i].table); } - for (i = 0; i < SYM_NUM; i++) { - if (p->sym_val_to_name[i]) - kfree(p->sym_val_to_name[i]); - } + for (i = 0; i < SYM_NUM; i++) + kfree(p->sym_val_to_name[i]); - if (p->class_val_to_struct) - kfree(p->class_val_to_struct); - if (p->role_val_to_struct) - kfree(p->role_val_to_struct); - if (p->user_val_to_struct) - kfree(p->user_val_to_struct); + kfree(p->class_val_to_struct); + kfree(p->role_val_to_struct); + kfree(p->user_val_to_struct); avtab_destroy(&p->te_avtab); diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index b6149147d5cb..922bb45054aa 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -1705,11 +1705,9 @@ out: err: if (*names) { for (i = 0; i < *len; i++) - if ((*names)[i]) - kfree((*names)[i]); + kfree((*names)[i]); } - if (*values) - kfree(*values); + kfree(*values); goto out; } -- cgit v1.2.3 From 6931dfc9f3f81d148b7ed0ab3fd796f8b986a995 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Thu, 30 Jun 2005 02:58:51 -0700 Subject: [PATCH] selinux_sb_copy_data() should not require a whole page Currently selinux_sb_copy_data requires an entire page be allocated to *orig when the function is called. This "requirement" is based on the fact that we call copy_page(in_save, nosec_save) and in_save = orig when the data is not FS_BINARY_MOUNTDATA. This means that if a caller were to call do_kern_mount with only about 10 bytes of options, they would get passed here and then we would corrupt PAGE_SIZE - 10 bytes of memory (with all zeros.) Currently it appears all in kernel FS's use one page of data so this has not been a problem. An out of kernel FS did just what is described above and it would almost always panic shortly after they tried to mount. From looking else where in the kernel it is obvious that this string of data must always be null terminated. (See example in do_mount where it always zeros the last byte.) Thus I suggest we use strcpy in place of copy_page. In this way we make sure the amount we copy is always less than or equal to the amount we received and since do_mount is zeroing the last byte this should be safe for all. Signed-off-by: Eric Paris Cc: Stephen Smalley Acked-by: James Morris Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- security/selinux/hooks.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'security/selinux') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 17a1189f1ff8..6be273851144 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -68,6 +68,7 @@ #include #include #include +#include #include "avc.h" #include "objsec.h" @@ -1943,7 +1944,7 @@ static int selinux_sb_copy_data(struct file_system_type *type, void *orig, void } } while (*in_end++); - copy_page(in_save, nosec_save); + strcpy(in_save, nosec_save); free_page((unsigned long)nosec_save); out: return rc; -- cgit v1.2.3