[PATCH] sns: check related executable memory of binaries [3/4]

2007-06-22 Thread Alexander Wuerstlein
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]

2007-06-22 Thread Alexander Wuerstlein
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]

2007-06-21 Thread Alexander Wuerstlein
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]

2007-06-21 Thread Alexander Wuerstlein
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