[PATCH] sns: check related executable memory of binaries [3/4]
From: Johannes Schlumberger <[EMAIL PROTECTED]> Checks on mmap and mprotect (i.e. libraries) wether they are signed and adjusts the processe's signed flag accordingly. If a process looses its signed state it gets, in our current design, killed, for it is no longer trustworthy. A process also looses its signed flag if it mprotects any memory as executable. Signed-off-by: Johannes Schlumberger <[EMAIL PROTECTED]> --- include/linux/mm.h |3 ++ include/linux/sns.h | 17 +++ kernel/fork.c |7 mm/mmap.c | 79 +++ mm/mprotect.c | 30 +++ security/Kconfig| 36 +++ security/sns.c | 10 ++ 7 files changed, 176 insertions(+), 6 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index e4183c6..903bc45 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -112,6 +112,9 @@ struct vm_area_struct { #ifdef CONFIG_NUMA struct mempolicy *vm_policy;/* NUMA policy for the VMA */ #endif +#ifdef CONFIG_SNS_SIGNED + int sns_valid_sig; +#endif }; extern struct kmem_cache *vm_area_cachep; diff --git a/include/linux/sns.h b/include/linux/sns.h index ad15e4b..eefb6e7 100644 --- a/include/linux/sns.h +++ b/include/linux/sns.h @@ -1,3 +1,20 @@ #ifdef CONFIG_SNS_SIGNED int sns_signature_valid(struct file *); +int sns_signature_becomes_invalid(void); + +/* + * The following is unfortunately necessary, there does not seem to be a + * common define to find out wether some ominous DSO which somebody + * likes to mmap or mprotect is in fact trustworthy kernel code. + */ +#ifdef CONFIG_X86 +#define sns_is_gate_vdso(addr, len) (addr==0xe000 && len == PAGE_SIZE) +#else +#ifdef CONFIG_IA64 +#define sns_is_gate_vdso(addr, len) (addr==0xe000UL && len == PAGE_SIZE) +#else +#define sns_is_gate_vdso(addr, len) 0 +#endif +#endif + #endif diff --git a/kernel/fork.c b/kernel/fork.c index c12cf61..b1afa57 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -260,6 +260,9 @@ static inline int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) file = tmp->vm_file; if (file) { struct inode *inode = file->f_path.dentry->d_inode; +#ifdef CONFIG_SNS_SIGNED + tmp->sns_valid_sig = mpnt->sns_valid_sig; +#endif get_file(file); if (tmp->vm_flags & VM_DENYWRITE) atomic_dec(>i_writecount); @@ -271,6 +274,10 @@ static inline int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) vma_prio_tree_add(tmp, mpnt); flush_dcache_mmap_unlock(file->f_mapping); spin_unlock(>f_mapping->i_mmap_lock); +#ifdef CONFIG_SNS_SIGNED + } else { + tmp->sns_valid_sig = 0; +#endif } /* diff --git a/mm/mmap.c b/mm/mmap.c index 68b9ad2..1f4bdf0 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -25,6 +25,9 @@ #include #include #include +#ifdef CONFIG_SNS_SIGNED +#include +#endif #include #include @@ -1101,10 +1104,33 @@ munmap_back: error = file->f_op->mmap(file, vma); if (error) goto unmap_and_free_vma; - } else if (vm_flags & VM_SHARED) { - error = shmem_zero_setup(vma); - if (error) - goto free_vma; +#ifdef CONFIG_SNS_SIGNED + if (current->sns_valid_sig && (vm_flags & VM_EXEC)) { + if (vm_flags & VM_WRITE){ + vma->sns_valid_sig = 0; + current->sns_valid_sig = 0; + sns_signature_becomes_invalid(); + } else { + vma->sns_valid_sig = sns_signature_valid(file); + current->sns_valid_sig = vma->sns_valid_sig; + if(!current->sns_valid_sig) + sns_signature_becomes_invalid(); + } + } +#endif + } else { +#ifdef CONFIG_SNS_SIGNED + /* JIT could have written some evil code here, which we are unable to verify */ + if (prot & PROT_EXEC && current->sns_valid_sig) { + if ((vma->sns_valid_sig = (current->sns_valid_sig = (sns_is_gate_vdso(addr, len) + sns_signature_becomes_invalid(); + } +#endif + if (vm_flags & VM_SHARED) { + error = shmem_zero_setup(vma); + if (error) + goto free_vma; + } } /* We set VM_ACCOUNT in a shared mapping's vm_flags, to inform @@ -1946,8 +1972,49 @@ unsigned long do_brk(unsigned long addr, unsigned long len)
[PATCH] sns: check related executable memory of binaries [3/4]
From: Johannes Schlumberger [EMAIL PROTECTED] Checks on mmap and mprotect (i.e. libraries) wether they are signed and adjusts the processe's signed flag accordingly. If a process looses its signed state it gets, in our current design, killed, for it is no longer trustworthy. A process also looses its signed flag if it mprotects any memory as executable. Signed-off-by: Johannes Schlumberger [EMAIL PROTECTED] --- include/linux/mm.h |3 ++ include/linux/sns.h | 17 +++ kernel/fork.c |7 mm/mmap.c | 79 +++ mm/mprotect.c | 30 +++ security/Kconfig| 36 +++ security/sns.c | 10 ++ 7 files changed, 176 insertions(+), 6 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index e4183c6..903bc45 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -112,6 +112,9 @@ struct vm_area_struct { #ifdef CONFIG_NUMA struct mempolicy *vm_policy;/* NUMA policy for the VMA */ #endif +#ifdef CONFIG_SNS_SIGNED + int sns_valid_sig; +#endif }; extern struct kmem_cache *vm_area_cachep; diff --git a/include/linux/sns.h b/include/linux/sns.h index ad15e4b..eefb6e7 100644 --- a/include/linux/sns.h +++ b/include/linux/sns.h @@ -1,3 +1,20 @@ #ifdef CONFIG_SNS_SIGNED int sns_signature_valid(struct file *); +int sns_signature_becomes_invalid(void); + +/* + * The following is unfortunately necessary, there does not seem to be a + * common define to find out wether some ominous DSO which somebody + * likes to mmap or mprotect is in fact trustworthy kernel code. + */ +#ifdef CONFIG_X86 +#define sns_is_gate_vdso(addr, len) (addr==0xe000 len == PAGE_SIZE) +#else +#ifdef CONFIG_IA64 +#define sns_is_gate_vdso(addr, len) (addr==0xe000UL len == PAGE_SIZE) +#else +#define sns_is_gate_vdso(addr, len) 0 +#endif +#endif + #endif diff --git a/kernel/fork.c b/kernel/fork.c index c12cf61..b1afa57 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -260,6 +260,9 @@ static inline int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) file = tmp-vm_file; if (file) { struct inode *inode = file-f_path.dentry-d_inode; +#ifdef CONFIG_SNS_SIGNED + tmp-sns_valid_sig = mpnt-sns_valid_sig; +#endif get_file(file); if (tmp-vm_flags VM_DENYWRITE) atomic_dec(inode-i_writecount); @@ -271,6 +274,10 @@ static inline int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) vma_prio_tree_add(tmp, mpnt); flush_dcache_mmap_unlock(file-f_mapping); spin_unlock(file-f_mapping-i_mmap_lock); +#ifdef CONFIG_SNS_SIGNED + } else { + tmp-sns_valid_sig = 0; +#endif } /* diff --git a/mm/mmap.c b/mm/mmap.c index 68b9ad2..1f4bdf0 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -25,6 +25,9 @@ #include linux/mount.h #include linux/mempolicy.h #include linux/rmap.h +#ifdef CONFIG_SNS_SIGNED +#include linux/sns.h +#endif #include asm/uaccess.h #include asm/cacheflush.h @@ -1101,10 +1104,33 @@ munmap_back: error = file-f_op-mmap(file, vma); if (error) goto unmap_and_free_vma; - } else if (vm_flags VM_SHARED) { - error = shmem_zero_setup(vma); - if (error) - goto free_vma; +#ifdef CONFIG_SNS_SIGNED + if (current-sns_valid_sig (vm_flags VM_EXEC)) { + if (vm_flags VM_WRITE){ + vma-sns_valid_sig = 0; + current-sns_valid_sig = 0; + sns_signature_becomes_invalid(); + } else { + vma-sns_valid_sig = sns_signature_valid(file); + current-sns_valid_sig = vma-sns_valid_sig; + if(!current-sns_valid_sig) + sns_signature_becomes_invalid(); + } + } +#endif + } else { +#ifdef CONFIG_SNS_SIGNED + /* JIT could have written some evil code here, which we are unable to verify */ + if (prot PROT_EXEC current-sns_valid_sig) { + if ((vma-sns_valid_sig = (current-sns_valid_sig = (sns_is_gate_vdso(addr, len) + sns_signature_becomes_invalid(); + } +#endif + if (vm_flags VM_SHARED) { + error = shmem_zero_setup(vma); + if (error) + goto free_vma; + } } /* We set VM_ACCOUNT in a shared mapping's vm_flags, to inform @@ -1946,8 +1972,49 @@ unsigned long
[PATCH] sns: check related executable memory of binaries [3/4]
From: Johannes Schlumberger <[EMAIL PROTECTED]> Checks on mmap and mprotect (i.e. libraries) wether they are signed and adjusts the processe's signed flag accordingly. If a process looses its signed state it gets, in our current design, killed, for it is no longer trustworthy. A process also looses its signed flag if it mprotects any memory as executable. Signed-off-by: Johannes Schlumberger <[EMAIL PROTECTED]> --- include/linux/mm.h |3 ++ include/linux/sns.h | 17 +++ kernel/fork.c |7 mm/mmap.c | 79 +++ mm/mprotect.c | 30 +++ security/Kconfig| 36 +++ security/sns.c | 10 ++ 7 files changed, 176 insertions(+), 6 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index e4183c6..903bc45 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -112,6 +112,9 @@ struct vm_area_struct { #ifdef CONFIG_NUMA struct mempolicy *vm_policy;/* NUMA policy for the VMA */ #endif +#ifdef CONFIG_SNS_SIGNED + int sns_valid_sig; +#endif }; extern struct kmem_cache *vm_area_cachep; diff --git a/include/linux/sns.h b/include/linux/sns.h index ad15e4b..eefb6e7 100644 --- a/include/linux/sns.h +++ b/include/linux/sns.h @@ -1,3 +1,20 @@ #ifdef CONFIG_SNS_SIGNED int sns_signature_valid(struct file *); +int sns_signature_becomes_invalid(void); + +/* + * The following is unfortunately necessary, there does not seem to be a + * common define to find out wether some ominous DSO which somebody + * likes to mmap or mprotect is in fact trustworthy kernel code. + */ +#ifdef CONFIG_X86 +#define sns_is_gate_vdso(addr, len) (addr==0xe000 && len == PAGE_SIZE) +#else +#ifdef CONFIG_IA64 +#define sns_is_gate_vdso(addr, len) (addr==0xe000UL && len == PAGE_SIZE) +#else +#define sns_is_gate_vdso(addr, len) 0 +#endif +#endif + #endif diff --git a/kernel/fork.c b/kernel/fork.c index c12cf61..b1afa57 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -260,6 +260,9 @@ static inline int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) file = tmp->vm_file; if (file) { struct inode *inode = file->f_path.dentry->d_inode; +#ifdef CONFIG_SNS_SIGNED + tmp->sns_valid_sig = mpnt->sns_valid_sig; +#endif get_file(file); if (tmp->vm_flags & VM_DENYWRITE) atomic_dec(>i_writecount); @@ -271,6 +274,10 @@ static inline int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) vma_prio_tree_add(tmp, mpnt); flush_dcache_mmap_unlock(file->f_mapping); spin_unlock(>f_mapping->i_mmap_lock); +#ifdef CONFIG_SNS_SIGNED + } else { + tmp->sns_valid_sig = 0; +#endif } /* diff --git a/mm/mmap.c b/mm/mmap.c index 68b9ad2..1f4bdf0 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -25,6 +25,9 @@ #include #include #include +#ifdef CONFIG_SNS_SIGNED +#include +#endif #include #include @@ -1101,10 +1104,33 @@ munmap_back: error = file->f_op->mmap(file, vma); if (error) goto unmap_and_free_vma; - } else if (vm_flags & VM_SHARED) { - error = shmem_zero_setup(vma); - if (error) - goto free_vma; +#ifdef CONFIG_SNS_SIGNED + if (current->sns_valid_sig && (vm_flags & VM_EXEC)) { + if (vm_flags & VM_WRITE){ + vma->sns_valid_sig = 0; + current->sns_valid_sig = 0; + sns_signature_becomes_invalid(); + } else { + vma->sns_valid_sig = sns_signature_valid(file); + current->sns_valid_sig = vma->sns_valid_sig; + if(!current->sns_valid_sig) + sns_signature_becomes_invalid(); + } + } +#endif + } else { +#ifdef CONFIG_SNS_SIGNED + /* JIT could have written some evil code here, which we are unable to verify */ + if (prot & PROT_EXEC && current->sns_valid_sig) { + if ((vma->sns_valid_sig = (current->sns_valid_sig = (sns_is_gate_vdso(addr, len) + sns_signature_becomes_invalid(); + } +#endif + if (vm_flags & VM_SHARED) { + error = shmem_zero_setup(vma); + if (error) + goto free_vma; + } } /* We set VM_ACCOUNT in a shared mapping's vm_flags, to inform @@ -1946,8 +1972,49 @@ unsigned long do_brk(unsigned long addr, unsigned long len)
[PATCH] sns: check related executable memory of binaries [3/4]
From: Johannes Schlumberger [EMAIL PROTECTED] Checks on mmap and mprotect (i.e. libraries) wether they are signed and adjusts the processe's signed flag accordingly. If a process looses its signed state it gets, in our current design, killed, for it is no longer trustworthy. A process also looses its signed flag if it mprotects any memory as executable. Signed-off-by: Johannes Schlumberger [EMAIL PROTECTED] --- include/linux/mm.h |3 ++ include/linux/sns.h | 17 +++ kernel/fork.c |7 mm/mmap.c | 79 +++ mm/mprotect.c | 30 +++ security/Kconfig| 36 +++ security/sns.c | 10 ++ 7 files changed, 176 insertions(+), 6 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index e4183c6..903bc45 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -112,6 +112,9 @@ struct vm_area_struct { #ifdef CONFIG_NUMA struct mempolicy *vm_policy;/* NUMA policy for the VMA */ #endif +#ifdef CONFIG_SNS_SIGNED + int sns_valid_sig; +#endif }; extern struct kmem_cache *vm_area_cachep; diff --git a/include/linux/sns.h b/include/linux/sns.h index ad15e4b..eefb6e7 100644 --- a/include/linux/sns.h +++ b/include/linux/sns.h @@ -1,3 +1,20 @@ #ifdef CONFIG_SNS_SIGNED int sns_signature_valid(struct file *); +int sns_signature_becomes_invalid(void); + +/* + * The following is unfortunately necessary, there does not seem to be a + * common define to find out wether some ominous DSO which somebody + * likes to mmap or mprotect is in fact trustworthy kernel code. + */ +#ifdef CONFIG_X86 +#define sns_is_gate_vdso(addr, len) (addr==0xe000 len == PAGE_SIZE) +#else +#ifdef CONFIG_IA64 +#define sns_is_gate_vdso(addr, len) (addr==0xe000UL len == PAGE_SIZE) +#else +#define sns_is_gate_vdso(addr, len) 0 +#endif +#endif + #endif diff --git a/kernel/fork.c b/kernel/fork.c index c12cf61..b1afa57 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -260,6 +260,9 @@ static inline int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) file = tmp-vm_file; if (file) { struct inode *inode = file-f_path.dentry-d_inode; +#ifdef CONFIG_SNS_SIGNED + tmp-sns_valid_sig = mpnt-sns_valid_sig; +#endif get_file(file); if (tmp-vm_flags VM_DENYWRITE) atomic_dec(inode-i_writecount); @@ -271,6 +274,10 @@ static inline int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) vma_prio_tree_add(tmp, mpnt); flush_dcache_mmap_unlock(file-f_mapping); spin_unlock(file-f_mapping-i_mmap_lock); +#ifdef CONFIG_SNS_SIGNED + } else { + tmp-sns_valid_sig = 0; +#endif } /* diff --git a/mm/mmap.c b/mm/mmap.c index 68b9ad2..1f4bdf0 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -25,6 +25,9 @@ #include linux/mount.h #include linux/mempolicy.h #include linux/rmap.h +#ifdef CONFIG_SNS_SIGNED +#include linux/sns.h +#endif #include asm/uaccess.h #include asm/cacheflush.h @@ -1101,10 +1104,33 @@ munmap_back: error = file-f_op-mmap(file, vma); if (error) goto unmap_and_free_vma; - } else if (vm_flags VM_SHARED) { - error = shmem_zero_setup(vma); - if (error) - goto free_vma; +#ifdef CONFIG_SNS_SIGNED + if (current-sns_valid_sig (vm_flags VM_EXEC)) { + if (vm_flags VM_WRITE){ + vma-sns_valid_sig = 0; + current-sns_valid_sig = 0; + sns_signature_becomes_invalid(); + } else { + vma-sns_valid_sig = sns_signature_valid(file); + current-sns_valid_sig = vma-sns_valid_sig; + if(!current-sns_valid_sig) + sns_signature_becomes_invalid(); + } + } +#endif + } else { +#ifdef CONFIG_SNS_SIGNED + /* JIT could have written some evil code here, which we are unable to verify */ + if (prot PROT_EXEC current-sns_valid_sig) { + if ((vma-sns_valid_sig = (current-sns_valid_sig = (sns_is_gate_vdso(addr, len) + sns_signature_becomes_invalid(); + } +#endif + if (vm_flags VM_SHARED) { + error = shmem_zero_setup(vma); + if (error) + goto free_vma; + } } /* We set VM_ACCOUNT in a shared mapping's vm_flags, to inform @@ -1946,8 +1972,49 @@ unsigned long